AISELL项目总结

                AISELL项目总结

系统项目集成:

1. 指定框架使用版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>4.2.5.RELEASE</org.springframework.version>
<org.hibernate.version>4.3.8.Final</org.hibernate.version>
<spring-data-jpa.version>1.9.0.RELEASE</spring-data-jpa.version>
<com.fasterxml.jackson.version>2.5.0</com.fasterxml.jackson.version>
<org.slf4j.version>1.6.1</org.slf4j.version>
</properties>

<dependencies>
<!-- Spring的支持包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<!-- 引入web前端的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- SpringMCV上传需要用到io-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 文件上传用到的包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<!-- SpringMVCjson支持包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${com.fasterxml.jackson.version}</version>
</dependency>
<!-- hibernate的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${org.hibernate.version}</version>
</dependency>
<!-- SpringData的支持包 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
</dependency>
<!-- SpringData的擴展包 -->
<dependency>
<groupId>com.github.wenhao</groupId>
<artifactId>jpa-spec</artifactId>
<version>3.1.1</version>
<!-- 把所有的依賴都去掉 -->
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<!-- 測試包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!-- 这个scope 只能作用在编译和测试时,同时没有传递性。表示在运行的时候不添加此jar文件 -->
<scope>provided</scope>
</dependency>
<!-- 日志文件 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<!-- 代码生成器模版技术 freemark -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.6</version>
</dependency>
<!-- shiro的支持包 权限框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.4.0</version>
<type>pom</type>
</dependency>
<!-- shiroSpring的集成包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- poi支持的jar包 导入导出 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<!-- 图片压缩功能 -->
<!-- 缩略图 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.6</version>
</dependency>
<!-- 定时调度 -->
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
<version>1.5.2</version>
</dependency>
<!-- 邮件支持 -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>

<build>
<finalName>yxb</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.15.v20140411</version>
<configuration>
<stopPort>9966</stopPort>
<stopKey>foo</stopKey>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>

 

完成service层的接口:

 

创建IBaseService接口:里面提供公共的方法

 

 

 

 

再用其他的普通接口去继承这个公共的接口就会会得里面的所有方法:

 

子接口:

 

 

 

 

 

 

用一个公共类去实现那个公共接口复写里面的公共方法  其他的实现类去继承那个实现类并且实现自己的接口:

 

//@Service
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class BaseServiceImpl<T,ID extends Serializable> implements IBaseService<T,ID> {

//spring 4之后 支持泛型的注解
@Autowired
private BaseRepository<T,ID> baseRepository;

@Override
@Transactional
public void save(T t) {
baseRepository.save(t);
}

@Override
@Transactional
public void delete(ID id) {
baseRepository.delete(id);
}

@Override
public T findOne(ID id) {
return baseRepository.findOne(id);
}

@Override
public List<T> findAll() {
return baseRepository.findAll();
}

@Override
public Page findPageByQuery(BaseQuery baseQuery) {
return baseRepository.findPageByQuery(baseQuery);
}

@Override
public List<T> findByQuery(BaseQuery baseQuery) {
return baseRepository.findByQuery(baseQuery);
}

@Override
public List findByJpql(String jpql, Object... values) {
return baseRepository.findByJpql(jpql,values);
}
}

 

 子类:

 

 

 

 

 

 

集成springMVC:

 

引入相应的jar包:

 

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${org.springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${org.springframework.version}</version>
</dependency>

 

 配置 applicationContext-mvc.xml:

 

<!-- 对静态资源进行放行 -->
<mvc:default-servlet-handler />
<!-- 扫描controller部分的包 -->
<!-- @Component组件, @Repository持久层, @Service业务逻辑层, and @Controller控制器 -->
<context:component-scan base-package="cn.itsource.aisell.web.controller" />
<!-- 添加mvc@RequestMapping等注解的支持 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json; charset=UTF-8</value>
<value>application/x-www-form-urlencoded; charset=UTF-8</value>
</list>
</property>
<!-- No serializer:配置 setObjectMapper(new CustomMapper)objectMapper 为我们自定义扩展后的 CustomMapper,解决了返回对象有关系对象的报错问题 -->
<property name="objectMapper">
<bean class="cn.itsource.aisell.common.CustomMapper"></bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

<!-- ViewResolver 视图解析器 (struts2视图类型类似) -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 设置视图路径的前后缀,该配置可以让我们写视图路径的时候更简单。 -->
<!-- 希望跳转jsp[/WEB-INF/views/前缀][xxx变量][.jsp后缀] -->
<!-- * @see #setPrefix -->
<property name="prefix" value="/WEB-INF/views/" />
<!-- * @see #setSuffix -->
<property name="suffix" value=".jsp" />
</bean>

<!-- 错误:提示告诉开发者你没有配置文件上传解析器。 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为1MB -->
<property name="maxUploadSize">
<value>1048576</value>
</property>
</bean>

 

在配置applicationContext.XML:

 

 

 

<context:component-scan base-package="cn.itsource.aisell"></context:component-scan>
<!--jdbc.properties dataSource EntityManagerFactory Transaction-->
<!-- 加载配置jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置连接池dataSource bean生命周期方法 销毁方法close 用来连接之后 还给链接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 得到EntityManagerFactory 方言 链接池-->
<!-- 得到EntityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<!-- 配置属性 setDataSource-->
<property name="dataSource" ref="dataSource"></property>
<!-- 扫描实体类的配置 entity-->
<property name="packagesToScan" value="cn.itsource.aisell.domain"></property>

<property name="jpaVendorAdapter" >
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- 是否显示sql-->
<property name="showSql" value="true"></property>
<!-- 是否创建表-->
<property name="generateDdl" value="true"></property>
<!--数据库方言-->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"></property>
</bean>
</property>

</bean>

<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>

<!-- 开启事务 扫描@Transaction这种注解-->
<tx:annotation-driven/>

<!-- springdatajpa配置 引入事务和实体管理工厂-->
<jpa:repositories base-package="cn.itsource.aisell.repository"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"
factory-class="cn.itsource.aisell.repository.impl.BaseRepositoryFactoryBean">
</jpa:repositories>

<bean id="myBean" class="cn.itsource.aisell.bean.Mybean"></bean>

 

 

 

创建controller层并给以前端访问的路劲:

 

 

 

 @Controller
@RequestMapping("/employee")
public class EmployeeController {

@Autowired
private IEmployeeService employeeService;

@RequestMapping("/index")
public String index(){
return "employee";
}

//写一个方法查询数据 返回json --查数据库 findPage
@RequestMapping("/page")
@ResponseBody
public UiPage page(EmployeeQuery employeeQuery){
//List<Employee> employees = employeeService.findAll();
Page page = employeeService.findPageByQuery(employeeQuery);
UiPage uipage = new UiPage(page);
return uipage;
}
}

 

 找一个前端页面进行测试:能显示就代表环境搭建没有问题

 

 

 

 

 引入eazyui文件:

 

 

再用eazyui里面的属性的时候 就要引入eazyui很麻烦:抽取

 

 提取在一个公共的jsp里面  每个jsp去引入就行了

 

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>

<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">

<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
<!-- 获取查询表单里面数据js form里面数据 转换成对象-->
<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>
<!-- 公共的js文件-->
<script type="text/javascript" src="/js/common.js"></script>

 

 

 

删除:首先获取选中列的数

 

//getSelected获取选择表格的信息没有 没有返回false
var rom = employeeGrid.datagrid('getSelected')//获取选择的刚的数据信息

 

在判断有没有值如果有有值在发送ajax请求删除数据

 

//提示是否要删除 点击确定回调函数获取传进来的值进行删除发送ajax
$.messager.confirm('再次确认','删除后将永久无法恢复',function (value) {
if (value) {
//发送ajax请求到后台进行删除传一个id过去
$.get('/employee/delete',{"id":rom.id},function (date) {
if (date.success) {
$.messager.alert('提示:','删除成功','info');
//重新加载数据
employeeGrid.datagrid('reload');
}else{
$.messager.alert('温馨提示:','删除失败'+date.msg,'error');
}
})
}

})
}else{
$.message.alert('必须选择才能进行删除','info')
return
}

 

添加:首先定义一个对话框 里面定义一个form表单

 

    再给添加按钮绑定一个事件一点击就弹出对话框

 

定义form表单://定义form表单

 

 

 

绑定事件
var searchForm = $("#searchForm");

 

 

 

 

 

 

 

var itsource = {
search:function(){

},

 

 

 

 

 

 

 

add:function(){
//弹出一个对话框
employeeForm.form('clear')
//取消隐藏框
$("tr[data-save]").show();
//开启密码验证:enableValidation
$("*[data-save] input").validatebox("enableValidation");
employeeDialog.dialog('center').dialog('open');

},

 

 

 

save:function () {
/* var url = "/employee/add";//添加路劲
//获取隐藏域里面id
var id = $("#employeeId").val();
//判断隐藏域里面是否有ID值再来决定用哪个路径
if(id){
url = "/employee/update?cmd=update"//修改路劲
}*/
employeeForm.form('submit', {
//提交的路径
url: '/employee/add',
onSubmit: function () {
// 提交之前的验证
//validate返回boolean类型
return employeeForm.form('validate');
},
success: function (data) {
//发送ajax请求进行数据保存
//先将字符串转换为json对象
var dataJson= $.parseJSON(data);
//如果获取的有值就提示操作成功
if(dataJson.success){
$.messager.alert('提示:','提交成功','info');
//重新加载数据
employeeGrid.datagrid('reload');
//关闭对话框
employeeDialog.dialog('close');
}else{
$.messager.alert('警告:','提交失败','info')
employeeDialog.dialog('close');
}

}

});

 

 

 

 

 

employeeForm.form('submit', {
//提交的路径
url: '/employee/add',

 

 

 

修改:

 

首先修改和添加时进同一个表单   但是进修改表单的时候回取消密码验证 个隐藏密码框://隐藏数据 display:none密码
$("tr[data-save]").hide();
//取消密码验证:disableValidation
$("*[data-save] input").validatebox("disableValidation");

 

数据回显://修改 -- 回显示数据
employeeForm.form('load',row);

 

部门回显:

 

 

 

if(row.department){
row["department.id"] = row.department.id;
}

 

 

 

 

 

扩展功能 密码验证://取消密码验证:disableValidation
$("*[data-save] input").validatebox("disableValidation");
//开启密码验证$("*[data-save] input").validatebox("enableValidation");

 

 

 

数据丢失问题:在damain层里面头像字段上面设置@Column(updatable = false)代表不更新头像

 

 

 

//头像
//不更新头像
@Column(updatable = false)
private String headImage;

 

shorl权限验证

shiro介绍: Shiro是一个强大且易用的Java安全框架,身份验证授权密码学会话管理

 

 

Spring security 重量级安全框架(配置很麻烦 做的比较细)

 

Apache Shiro轻量级安全框架 (配置很容易 很方便,很容易使用)

 

shiro使用的地方:用户登录和登录权限验证

shiro入门:

导包:<dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

准备资源文件:shiro.ini文件

 

 

[users]
# 用户 'root' 密码是 'secret' and the 'admin' 角色
root = secret, admin
# 用户 'guest' 密码 'guest' 和'guest'角色
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# 用户 'darkhelmet' with password 'ludicrousspeed' and 角色 'darklord' and 'schwartz'
darkhelmet = 123, darklord, schwartz
# 用户 'lonestarr' 密码 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz

[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# 这个 'schwartz' 角色 能干lightsaber下面的所有事情:
schwartz = lightsaber:*
# goodguy这个角色 能干winnebago下面的drive权限,操作eagle5这个资源 user:delete:5
goodguy = winnebago:drive:eagle5

 

测试登录验证的权限:

//读取到shiro.ini文件,并且根据文件创建SecurityManager对象
// SecurityManager:权限的核心管理对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();

// 为了程序正常运行,需要设计一个这个securityManager(相当于把这个管理放到环境中去了)
SecurityUtils.setSecurityManager(securityManager);

//拿到当前用户【Subject:操作当前系统的一个用户】
Subject currentUser = SecurityUtils.getSubject();

//拿到一个会话(它在咱们的所有类型系统都可以使用【不要求必需是web项目】)
Session session = currentUser.getSession();
//会话操作【可以在会话中设置值与获取值】
session.setAttribute("someKey", "123456");
String value = (String) session.getAttribute("someKey");
if (value.equals("123456")) {
System.out.println("可以获取到这个值"+value);
}

//判断这个用户是否经过验证(没有登录我们可以认为是一个游客)
//没有登录,我们就可以完成登录
if (!currentUser.isAuthenticated()) {
//拿到用户名与密码令牌【拿到用户名与密码】
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//设置记住我的功能
token.setRememberMe(true);
try {
//完成登录功能
currentUser.login(token);
} catch (UnknownAccountException uae) {
//log.info("There is no user with username of " + token.getPrincipal());
//token.getPrincipal()[ˈprɪnsəpl] -> 拿到主体(登录用户的主要标识【用户名】)
System.out.println("这没有这个账号(用户名)"+token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
//incorrect [ˌɪnkəˈrekt]:不正确的,错误的
//Credentials[krəˈdenʃlz]:证书; 凭证,证件
//log.info("Password for account " + token.getPrincipal() + " was incorrect!");
System.out.println("这个密码是错误的"+token.getPrincipal());
} catch (LockedAccountException lae) {
System.out.println("这个账号已经被锁定");
}
//其它的登录失败异常【它是所有登录异常的父类】
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}

//用户登录成功
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

//判断这个用户是否是某一个角色
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}

//测试用户是否有某一个权限
if (currentUser.isPermitted("lightsaber:wield")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}

//a (very powerful) Instance Level permission:
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}

//登出(注销当前登录用户)
currentUser.logout();

System.exit(0);//退出虚拟机

自定权限验证:

 

1.首先一个类去继承AuthorizingRealm类会实现两个方法

 

//权限验证方法

 

 

 

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}

//用户名验证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}

 

 

 

用户验证测试//身份认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//得到令牌这个authenticationToken就是UsernamePasswordtoken
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//或得用户主体
Object principal = token.getPrincipal();
//获取前台传送的进来的用户名这个用户名是传过来的
String username = token.getUsername();
//这里根据用户名去获取密码
String password = getByName(username);
if(password==null){
return null;
}
else{
//账号密码传过来与自己的数据库进行比对
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password,null, getName());
return simpleAuthenticationInfo;
}

}
//这里根据用户名去获取密码
public String getByName(String username){
//后台的用户名和前台的进行对比如果过相等就返回123不等就返回null
if("haoge".equals(username)){
return "123";
}else{
return null;
}
}

 

 

 

 

 

//权限认证
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//拿到用户信息
String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();
//从数据库中拿到用户的权限
Set<String> roles = getRoleByPrincipal(primaryPrincipal);
//从数据库中去拿到用户的角色信息
Set<String> permissions = getPermissionByPrincipal(primaryPrincipal);

SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//设置获取角色
simpleAuthorizationInfo.setRoles(roles);
//设置获取的权限
simpleAuthorizationInfo.setStringPermissions(permissions);
//返回simpleAuthorizationInfo对象
return simpleAuthorizationInfo;
}

//模拟数据权限想信息
private Set<String> getPermissionByPrincipal(String primaryPrincipal) {
Set<String> permissions = new HashSet<String>();
if("haoge".equals(primaryPrincipal)){
//如果账号密码正确,就返回全部权限
permissions.add("driver:*");
return permissions;
}else{
return null;
}
}
//模拟数据库角色信息
private Set<String> getRoleByPrincipal(String primaryPrincipal) {
//创建一个集合
Set<String> roles = new HashSet<String>();
if("haoge".equals(primaryPrincipal)){
roles.add("admin");
return roles;
}else{
return null;
}
}

 

密码加密功能的完成

 

@Test
     public void testMyRealm() throws Exception{
         //创建自己定义的Realm
         MyRealm myRealm = new MyRealm();
        //Realm放到securityManager中去
         DefaultSecurityManager securityManager = new DefaultSecurityManager();
         securityManager.setRealm(myRealm);
         //把权限管理器放到相应的环境中(我们可以在项目任何位置拿到)
         SecurityUtils.setSecurityManager(securityManager);


         //设置咱们Realm的密码匹配器(我们的密码要怎么处理)
         HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
         matcher.setHashAlgorithmName("md5"); //匹配器使用MD5的算法
         matcher.setHashIterations(10);//加密算法要迭代多少次
         myRealm.setCredentialsMatcher(matcher);

         //拿到当前用户(Subject就是当前用户,游客)
         Subject currentUser = SecurityUtils.getSubject();
         //准备登录的令牌(准备用户名与密码) -> 这里的密码进行了加密
         UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");

         try {
             //根据令牌进行功能登录(当前用户进行登录)
             currentUser.login(token);
             System.out.println("登录成功啦。。。。");
         } catch (UnknownAccountException e) {
             System.out.println("这个账号不存在!" + token.getPrincipal());
             e.printStackTrace();
         } catch (IncorrectCredentialsException ice) {
             System.out.println("这个密码不存在!" + token.getPrincipal());
             ice.printStackTrace();
         }catch (AuthenticationException e){
             System.out.println("i don't k");
         }
     }

 

 

 

 

 

自定义Reaml加上盐值:

 

 

 

//进行登录的认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    //明显的知道:这个authenticationToken就是UsernamePasswordtoken
    UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
    String username = token.getUsername(); //拿到用户名(:这个用户名是传过来的)

    //这里根据用户名去获取密码(如果没有获取到,相当于这个用户不存在,就返回陪我)
    String password = getByName(username);
    if(password==null){
        return null;
    }
    //在这里加盐值需一个ByteSource对象,而Shiro提供了一个ByteSource对象给咱们
    ByteSource salt = ByteSource.Util.bytes("itsource");
    //创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
    return authenticationInfo;
}

private String getByName(String username) {
    if("admin".equals(username)){
        // 4a95737b032e98a50c056c41f2fa9ec6: 123456 迭代10次不加盐的结果
        // 831d092d59f6e305ebcfa77e05135eac: 123456 迭代10次加盐(itsource)的结果
        return "831d092d59f6e305ebcfa77e05135eac"; //修改为加密加盐后的数据
    }else if("guest".equals(username)){
        return "abcd";
    }
    return null;
}

 

 

 

 

 

Shiro集成Spring:我们的项目基本都是通过Spring来管理bean的,如果要想使用Shiro,那就要把shiro集成到Spring。集成Spring的核心就是把shiro框架的核心类(SecurityManager,Subject,Realm)交给Spring管理

导入集成的包: <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-all</artifactId>
    <version>1.4.0</version>
    <type>pom</type>
</dependency>
  <!-- shiroSpring的集成包 -->
  <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
  </dependency>

 

web.xml配置文件:

 

<filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <param-name>targetFilterLifecycle</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>shiroFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

 


配置过滤器:

 

<!-- 1.配置apache的管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 配置一个realm,到数据库中获取权限数据 -->
        <property name="realm" ref="jpaRealm"/>
    </bean>


    <!-- 2.我们可以自定义一个realm【暂时未实现功能】这个必需实现org.apache.shiro.realm.Realm接口 -->
    <bean id="jpaRealm" class="cn.itsource.yxb.shiro.realm.JpaRealm">
    </bean>

    <!-- 3.lifecycleBeanPostProcessor:可以自动调用在Spring Ioc窗口中 Shiro bean的生成周期方法 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 4.启动ioc容器中使用 shiro的注解,但是必需配置在Spring Ioc容器中Shiro bean的生成周期方法 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- 5.shiro的真实过滤器(注:这个名称必需和web.xml的代表过滤器【DelegatingFilterProxy】名称一样) -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!-- 登录的url,如果没有登录,你访问的路径会跳到这个页面 -->
        <property name="loginUrl" value="/s/login.jsp"/>
        <!-- 登录成功的url,如果登录成功,会跳转到这个页面 -->
        <property name="successUrl" value="/s/main.jsp"/>
        <!-- 没有权限时跳转到这个位置 -->
        <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
        <!--
            配置哪些资源被保护,哪些资源需要权限
            anon:不需要登录也可以访问相应的权限
            authc:需要权限才能访问
              /** :所有文件及其子文件
        -->
        <property name="filterChainDefinitions">
            <value>
                /s/login.jsp = anon
                /** = authc
            </value>
        </property>
    </bean>

 


权限菜单的功能实现

1.shiro根据登录的用户名把所有的权限从数据库查询出来


//通过用户主体ID查询数据库权限
Set<String> permissionsByLoginUser = iPermissionService.findPermissionsByLoginUser(employee.getId());

2.当前用户具备的权限查询出来交给shiro管理


SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

3.把查询出来的结果放在map集合里面


//查询出所有权限
List<Permission> all = iPermissionService.findAll();

for (Permission permission : all) {
String url = permission.getUrl();
String sn = permission.getSn();

mp.put(url, "perms["+sn +"]");
}

3当我们来访问的时候,根据url(key) --去shiro是否有对应的value (shiro里面做判断处理,如果

发现你没有权限,返回的没有权限的页面)


复写底层的方法解决


 


@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {

Subject subject = this.getSubject(request, response);
if (subject.getPrincipal() == null) {
this.saveRequestAndRedirectToLogin(request, response);
} else {
//如果拦截请求是ajax请求,返回json来处理 否者就返回页面
//X-Requested-With
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse)response;

//获取请求头
String header = req.getHeader("X-Requested-With");
if("XMLHttpRequest".equals(header)){
//返回json {"success":false,"msg":"没有权限"}
resp.setContentType("text/json;charset=UTF-8");
resp.getWriter().print("{\"success\":false,\"msg\":\"没有权限\"}");
}else {
//返回页面
String unauthorizedUrl = this.getUnauthorizedUrl();
if (StringUtils.hasText(unauthorizedUrl)) {
WebUtils.issueRedirect(request, response, unauthorizedUrl);
} else {
WebUtils.toHttp(response).sendError(401);
}
}
}

return false;

}
导入导出功能的实现:

jxl:只能对Excel进行操作,属于比较老的框架


 


 


POI:是apache的项目,可对msword,Excel,PPT进行操作,包括office20032007。对两种版本的处理都比较好。具体操作请看官方的文档。


 


excel的使用场景:excel和word这些都是办公的软件,但是有时候系统需要结合办公软件来使用,比如经常用户要求查询

那些部门的销售情况销和人数的时候


 


poi的使用:引入需要的 包


<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.11</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>3.11</version>
</dependency>


完成一个99乘法表的导出:


 


public void testPoiWrite99() throws Exception{
//创建一个工作薄
XSSFWorkbook workbook = new XSSFWorkbook();
//创建一个表格
XSSFSheet sheet = workbook.createSheet("99乘法表");
for (int i = 1; i <=9 ; i++) {
//9 1*1
// 1*2 2*2
XSSFRow row = sheet.createRow(i-1);
for (int j = 1; j <= i ; j++) {
//创建一个单元格
XSSFCell cell = row.createCell(j-1);
cell.setCellValue(i+"*"+j+"="+(i*j));
}

}
//输出
FileOutputStream out = new FileOutputStream(
new File("99.xlsx"));
workbook.write(out);
out.close();
}

SpringMVC  POI整合导入导出:


SpringMVC上传配置


<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize">
        <value>1048576</value>
    </property>
</bean>


 


准备上传的按钮:


 


<form id="searchForm" action="/employee/download" method="post">
用户名: <input name="username" class="easyui-textbox" style="width:80px;height:32px">
邮件: <input name="email" class="easyui-textbox" style="width:80px;height:32px">
部门 :
<input class="easyui-combobox" name="departmentId"
data-options="valueField:'id',textField:'name',panelHeight:'auto',url:'/util/departmentList'">
<a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查找</a>
<%--默认提交到form表单路劲--%>
<button class="easyui-linkbutton" iconCls="icon-redo">导出</button>
</form>

<form></form>标签提交的路劲导controller层


@RequestMapping("/import")
public class ImportController extends BaseController {

//跳转到导入页面
@RequestMapping("/index")
public String index(){
return "import";
}

//跳转到导入页面
@RequestMapping("/xlsx")
public String importXlsx(MultipartFile xlsxFile) throws Exception{
System.out.println(xlsxFile.getContentType()); //文件的类型(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
System.out.println(xlsxFile.getName()); //文件的名称(xlsxFile)
System.out.println(xlsxFile.getOriginalFilename());//文件的名称(employee-3.xlsx)
System.out.println(xlsxFile.getSize()); //文件的大小
return "import";
}

准备上传的一个方法:


public static List<String[]> importExcel(InputStream is) throws Exception{
//.准备装数据的容器
List<String[]> list = new ArrayList<>();
//1.读取一个Excel文件(内存中)
Workbook wb = new XSSFWorkbook(is);
//2.拿到第个sheet
Sheet sheet = wb.getSheetAt(0);
//3.拿到wb中的行(不要拿头部)
int lastRowNum = sheet.getLastRowNum();
for (int i = 1; i <= lastRowNum; i++) {
Row row = sheet.getRow(i);
//4.拿到每一列(格子)
short lastCellNum = row.getLastCellNum();
//.准备一个String[]装一行数据(有几列就有几条数据)
String[] data = new String[lastCellNum];
for (int j = 0; j < lastCellNum; j++) {
Cell cell = row.getCell(j);
data[j] = cell.getStringCellValue();
}
//.把一行数据写到集合中去
list.add(data);
}
return list;
}

最后成功了给出提示:


@RequestMapping("/xlsx")
public String importXlsx(MultipartFile xlsxFile, Model model) throws Exception{
//拿到上传的数据
List<String[]> list = ExcelUtils.importExcel(xlsxFile.getInputStream());
int count = 0;
for (int i = 0; i < list.size(); i++) {
//拿到每一行数据
String[] data = list.get(i);
//准备Employee对象进行数据放置
Employee employee = new Employee();
employee.setUsername(data[0]+ UUID.randomUUID().toString().substring(0,5));//随机一个名称
employee.setPassword(data[1]);
employee.setEmail(data[2]);
String age = data[3];
if(StringUtils.isNotBlank(age)){
employee.setAge(Integer.parseInt(age));
}
//拿到与设置部门
String deptName = data[4];
if(StringUtils.isNotBlank(deptName)){
Department department = departmentService.findByName(deptName)[这个方法需要根据用户名去拿到相应的部门,我们不在笔记中体现与完成这个方法,希望同学们是可以自己把这个简单的小功能补齐!];
employee.setDepartment(department);
}
employeeService.save(employee);
count ++;
}
//给出成功提示
model.addAttribute("count","成功导入"+count+"条数据!");
return "import";
}

springMVC导入:


准备一个导入页面:


<html>
<head>
<title>Title</title>
<%@include file="/WEB-INF/views/head.jsp" %>
</head>
<body>
<!-- 上传必需是:postenctype="multipart/form-data"-->
<form action="/import/employeeXlsx" method="post" enctype="multipart/form-data">
<input class="easyui-filebox" name="empFile" style="width:80%"
data-options="prompt:'选择一个文件...',buttonText: '选择文件'" />
<button class="easyui-linkbutton">导入</button>
</form>
</body>
</html>

 

准备一个你要导入的文档:


进入controller层读取你要导入的文档最


 


@RequestMapping("/employeeXlsx1")
public String employeeXlsx1(MultipartFile empFile) throws Exception {

ImportParams params = new ImportParams();
params.setTitleRows(1);

//导入
List<Employee> list = ExcelImportUtil.importExcel(empFile.getInputStream(),
Employee.class, params);

for (Employee employee : list) {
System.out.println(employee);
//根据部门名称查询的部门对象
String deptName = employee.getDepartment().getName();
Department department = departmentService.findDepartmentByName(deptName);
//设置部门
employee.setDepartment(department);
    //设置初始密码
employee.setPassword("123456");
//System.out.println(employee.getDepartment().getName());
employeeService.save(employee);
}



return "import";
}

 最后添加验证功能:


//开启验证
params.setNeedVerfiy(true);
//开启自定义验证
params.setVerifyHandler(aisellEmployeeVerifyHander);

//导入
ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore(empFile.getInputStream(),
Employee.class, params);
//正确数据
for (Employee employee : result.getList()) {
System.out.println(employee);
//根据部门名称查询的部门对象
String deptName = employee.getDepartment().getName();
Department department = departmentService.findDepartmentByName(deptName);
//设置部门
employee.setDepartment(department);
employee.setPassword("123456");
//System.out.println(employee.getDepartment().getName());
employeeService.save(employee);
}

 


最后把导入的信息添加到数据库然后展示到页面上让用户查看:


@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception {

ImportParams params = new ImportParams();
params.setTitleRows(1);
//开启验证
params.setNeedVerfiy(true);
//开启自定义验证
params.setVerifyHandler(aisellEmployeeVerifyHander);

//导入
ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore(empFile.getInputStream(),
Employee.class, params);
//正确数据
for (Employee employee : result.getList()) {
System.out.println(employee);
//根据部门名称查询的部门对象
String deptName = employee.getDepartment().getName();
Department department = departmentService.findDepartmentByName(deptName);
//设置部门
employee.setDepartment(department);
employee.setPassword("123456");
//System.out.println(employee.getDepartment().getName());
employeeService.save(employee);
}

//错误的数据
for (Employee employee : result.getFailList()) {
System.out.println("错误数据:"+employee);
}

//传回前台 让用户查看 修改
if(result.isVerfiyFail()){
//有时候信息
Workbook failWorkbook = result.getFailWorkbook();
//输出设置一堆参数
//把这个文件导出
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //mime类型
response.setHeader("Content-disposition", "attachment;filename=error.xlsx");
response.setHeader("Pragma", "No-cache");//设置不要缓存
//输出内容
OutputStream ouputStream = response.getOutputStream();
failWorkbook.write(ouputStream);
ouputStream.flush();
ouputStream.close();

}



return "import";
}
采购单 设计:

采购单设计:


    


    如图可知采购订单中的字段分别有   供应商   审核人   采购员  订单状态   交易时间  订单明细表  产品数量  产品小计 产品价格 产品描述


    那么他们之间的关系:供应商  -->  产品  (多对一), 产品-->产品订单明细表,产品-->采购员(多对一),如图配置   采购单-->供应商



 


高级查询:通过订单的时间和状态进行查询


public Specification createSpecification() {

Date tempDate = null;
if(this.endDate!=null){
tempDate = DateUtils.addDays(this.endDate,1 );
System.out.println(tempDate);
}

Specification<Purchasebill> spe = Specifications.<Purchasebill>and().
ge(this.beginDate != null, "vdate",this.beginDate ).
lt(this.endDate!=null,"vdate",tempDate).
eq(this.status!=null && !"".equals(this.status),"status",this.status)
.build();

return spe;
}

时间的转换:可以加在字段上面 也可以加在set方法上面



高级查询的流程:



通过JS绑定事件过后他会根据你传入的数据自动封装成对象传到加在路劲的page查询里面:



传到controller层:controller就收传过来的数据进行调用方法查询



 调用条件查询的方法


最后返回json数据加载到页面


 


 按钮绑定事件:



多表的格式转换:



状态的格式转换:



 删除:获取选中刚的数据判断有没有值 有值就传个id到后台进行删除


 


 采购明细单:http://www.easyui-extlib.com/


 下载完后引入资源文件:


<script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.getColumnInfo.js"></script>
<script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.editors.js"></script>
<script src="/easyui/plugin/cellEdit/jeasyui.extensions.datagrid.edit.cellEdit.js"></script>

采购单属性定义:


$(function () {
//明细表格
var dg = $("#gridItem"),
//默认行
defaultRow = { productId: "", color: "", smallpic: "", num: 0, price: 0, amount: 0, descs: "" },
insertPosition = "bottom";//插的位置

//表格初始化
var dgInit = function () {
//得到所有列
var getColumns = function () {
var result = [];
//具体列的配置
var normal = [
{
field: 'productId', title: '产品', width: 180,
editor: {
type: "combobox",
options: {
required: true,
valueField:'id',
textField:'name',
url:'/util/findAllProduct',
panelHeight:'auto'
}
},
formatter:function(value,row){
//value当前这个单元格的值 row整个行的值
return value.name;
}
},
{
field: 'color', title: '颜色', width: 180,
/* editor: {
type: "validatebox",
options: {
required: false,
readonly: true
}
},*/
formatter:function(value,row){
console.log(value);
console.log(row.productId.color);
if(row && row.productId){
return "<div style='width:20px;height:20px;">productId.color+"' ></div>"
}
}
},
{
field: 'smallpic', title: '图片', width: 100,
formatter:function(value,row){
console.log(row.productId);
if(row && row.productId.smallPic){
return "<img src='"+row.productId.smallPic+"' width='20px' height='20px'/>"
}
}
},
{
field: 'num', title: '产品数量', width: 100,
editor: {
type: "numberbox",
options: {
required: true
}
}
},
{
field: 'price', title: '价格', width: 100,
editor: {
type: "numberbox",
required: true
}
},
{
field: 'amount', title: '小计', width: 100,
formatter:function(value,row){
//小计
if(row.num && row.price) {
return row.num * row.price;
}
}
},
{
field: 'descs', title: '备注', width: 100,
editor: {
type: "text"
}
}
];
result.push(normal);

return result;
};
//设置表格配置
var options = {
idField: "productId",
rownumbers: true,
fitColumns: true,
fit: true,
border: true,//边框
singleSelect: true,
toolbar:"#itemBtns",
columns: getColumns(),//得到所有列
//表示开启单元格编辑功能
enableCellEdit: true
};

//创建编辑表格
dg.datagrid(options);

};

//定义方法 得到插入的行的索引
var getInsertRowIndex = function () {
return insertPosition == "top" ? 0 : dg.datagrid("getRows").length;
}

//按钮的绑定的事件
var buttonBindEvent = function () {
//插入行的按钮
$("#btnInsert").click(function () {
//获取插入表里面位置 最末尾
var targetIndex = getInsertRowIndex(),targetRow = $.extend({}, defaultRow, { ID: $.util.guid() });
//在表格里面添加一行
dg.datagrid("insertRow", { index: targetIndex, row: targetRow });
//插入一行之后,定义到第一个单元格
dg.datagrid("editCell", { index: 0, field: "productId" });
});
//删除表格里面单元格
$("#btnRemove").click(function () {
//得到选中的行
var row = dg.datagrid('getSelected');
if(row) {
//得到行索引
var index = dg.datagrid('getRowIndex', row);
//通过索引删除
dg.datagrid('deleteRow',index);
}
});
};

//调用初始化表格 创建表格
dgInit();
buttonBindEvent();//绑定事件


});

添加明细单的时候提交额外的参数:


 public Map save(Purchasebill purchasebill){
Map mp = new HashMap();
try {

List<Purchasebillitem> items = purchasebill.getItems();
BigDecimal totalAmount = new BigDecimal("0");
BigDecimal totalNum = new BigDecimal("0");

for (Purchasebillitem item : items) {
//算总的数量
totalNum = totalNum.add(item.getNum());
//计算小计
item.setAmount(item.getPrice().multiply(item.getNum()));
//算总的金额
totalAmount = totalAmount.add(item.getAmount());
//双向多对一 或一对多 一方放弃 建立多方到一方关系
item.setBill(purchasebill);

}
//主的采购单
purchasebill.setTotalAmount(totalAmount);
purchasebill.setTotalNum(totalNum);

//录入人--登陆人
purchasebill.setInputUser(UserContext.getUser());
//级联保存
purchasebillService.save(purchasebill);
mp.put("success", true);
} catch (Exception e) {
e.printStackTrace();
mp.put("success", false);
mp.put("msg", e.getMessage());
}
return mp;

}


 修改回显问题:


 public Map update(@ModelAttribute("editPurchasebill") Purchasebill purchasebill){
Map mp = new HashMap();
try {
//Purchasebill purchasebill = findOne(purchasebill.getId())

List<Purchasebillitem> items = purchasebill.getItems();
BigDecimal totalAmount = new BigDecimal("0");
BigDecimal totalNum = new BigDecimal("0");

for (Purchasebillitem item : items) {
//算总的数量
totalNum = totalNum.add(item.getNum());
//计算小计
item.setAmount(item.getPrice().multiply(item.getNum()));
//算总的金额
totalAmount = totalAmount.add(item.getAmount());
//双向多对一 或一对多 一方放弃 建立多方到一方关系
item.setBill(purchasebill);

}
//主的采购单
purchasebill.setTotalAmount(totalAmount);
purchasebillService.save(purchasebill);
purchasebill.setTotalNum(totalNum);


mp.put("success", true);
} catch (Exception e) {
e.printStackTrace();
mp.put("success", false);
mp.put("msg", e.getMessage());
}
return mp;

}


删除 解决notono问题:


删除删除完过后设置关联对象为null


 



 

报表分组

 

效果图:

 

 

Donmain层的配置:

 

private Long id; //编号

private String supplier; //供应商名称

private String buyer; //采购员名称

private String product; //产品名称

private String productType; //产品分类

private Date vdate; //交易时间

private BigDecimal num; //采购数量

private BigDecimal price; //价格

private BigDecimal amount; //小计 = 价格*数量

private Integer status;

private String groupField = ""; //分组字段

//构造方法简介建立关系
public PurchaseBillItemVo(Purchasebillitem item){
this.id=item.getId();
this.supplier=item.getBill().getSupplier().getName();
this.buyer=item.getBill().getBuyer().getUsername();
this.product=item.getProduct().getName();
this.productType=item.getProduct().getTypes().getName();
this.vdate=item.getBill().getVdate();
this.num=item.getNum();
this.price=item.getPrice();
this.amount=item.getAmount();
this.status=item.getBill().getStatus();

}
//分组
public PurchaseBillItemVo(Purchasebillitem item,String groupBy){
this.id = item.getId();
this.supplier = item.getBill().getSupplier().getName();
this.buyer = item.getBill().getBuyer().getUsername();
this.product = item.getProduct().getName();
this.productType = item.getProduct().getTypes().getName();
this.vdate = item.getBill().getVdate();
this.num = item.getNum();
this.price = item.getPrice();
this.amount = item.getAmount();
this.status = item.getBill().getStatus();
//根据传入的条件 进行分组
if("o.bill.supplier.name".equals(groupBy)){
this.groupField = this.supplier;
}else if("o.bill.buyer.username".equals(groupBy)){
this.groupField = this.buyer;
}else if("MONTH(o.bill.vdate)".equals(groupBy)){
//this.groupField = this.vdate; 7 8
this.groupField = (DateUtils.toCalendar(this.vdate).get(Calendar.MONTH)+1)+"";
}else{
this.groupField = this.supplier;
}
}
//无参
public PurchaseBillItemVo (){}


public String getGroupField() {
//设置分组字段 默认按照供应商分组
// this.groupField = this.supplier;
return groupField;
}

public void setGroupField(String groupField) {
this.groupField = groupField;
}

 

Service层方法的:

 

//分组方法的实现
@Override
public List<PurchaseBillItemVo> findItems(PurchasebillitemQuery itemQuery) {

List<Purchasebillitem> items = purchasebillitemRepository.findByQuery(itemQuery);

List<PurchaseBillItemVo> itemsvolist = new ArrayList<>();

for (Purchasebillitem item : items) {
PurchaseBillItemVo itemVo = new PurchaseBillItemVo(item,itemQuery.getGroupBy());
itemsvolist.add(itemVo);
}

return itemsvolist;
}

 

流程:点击报表加载数据进去conreoller层调用service的方法进行分组查询  返回json数据  前端页面自动封装

 

controller层map的封装:

 

饼状图的实现:

 

定义两个按钮分别为2D  3D定义在高级查询下面

 

 

引入饼状图需要的配置文件:

 

 

粘贴JS代码进行查询封装:

 

$(function(){
//定义form表单
var searchForm = $("#searchForm");
var purchasebillitemDialog = $("#purchasebillitemDialog");
$("a[data-method]").on('click',function(){
//获取 data-method属性 <a data-method="seacher">
var methodName = $(this).data("method");
//动态调用方法 itsource["seacher"]
itsource[methodName]();
});
//对象
var itsource = {
search:function(){
//该方法返回一个 JSON Object,返回对象中的每个数据都表示一个表单控件值。
var param = searchForm.serializeObject();
//发送查询数据库 --加载表格 发送请求 /purchasebillitem/page
$('#purchasebillitemDatagrid').datagrid('load',param);
},
charts3D:function(){
//发送ajax请求到后台查询的数据
var param = searchForm.serializeObject();
$.post("/purchaseBillItem/findAllGraphic",param,function(result){

Highcharts.chart('purchasebillitemDialog', {
chart: {
type: 'pie',
options3d: {
enabled: true,
alpha: 45, //倾斜角度
beta: 0
}
},
title: {
text: '比例图'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
depth: 35,//深度
dataLabels: {
enabled: true,
format: '{point.name}'
}
}
},
series: [{
type: 'pie',
name: '消费比例',
data:result
}]
});
})




//2D图表 --打开对话框
purchasebillitemDialog.dialog('center').dialog('open');
},
//2D事件
charts2D:function(){

var param = searchForm.serializeObject();
$.post("/purchaseBillItem/findAllGraphic",param,function(result){

Highcharts.chart('purchasebillitemDialog', {
chart: {
type: 'pie',
options3d: {
enabled: true,
alpha: 0, //倾斜角度
beta: 0
}
},
title: {
text: '比例图'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
depth: 35,//深度
dataLabels: {
enabled: true,
format: '{point.name}'
}
}
},
series: [{
type: 'pie',
name: '消费比例',
data:result
}]
});
})




purchasebillitemDialog.dialog('center').dialog('open');

}
}



});





$(function(){
$('#purchasebillitemDatagrid').datagrid({
width:500,
height:250,
fit:true,
rownumbers:true,
remoteSort:false,
nowrap:false,
fitColumns:true,
toolbar:'#tb',
url:'/purchaseBillItem/findAllItemVo',
columns:[[
{field:'id',title:'编号',width:100,sortable:true},
{field:'supplier',title:'供应商名称',width:80,align:'right',sortable:true},
{field:'buyer',title:'采购员名称',width:80,align:'right',sortable:true},
{field:'product',title:'产品名称',width:150,sortable:true},
{field:'productType',title:'产品分类',width:60,align:'center'},
{field:'vdate',title:'交易时间',width:180,align:'right',sortable:true},
{field:'num',title:'数量',width:50,sortable:true},
{field:'price',title:'价格',width:60,align:'center'},
{field:'amount',title:'小计',width:60,align:'center'},
{field:'status',title:'状态',width:60,align:'center',formatter:statusFormatter}
]],
groupField:'groupField',
view: groupview,
groupFormatter:function(value, rows){
var totalNum =0;
var totalAmount = 0;
//rows表示当前分组下面的行
for(var i=0;i<rows.length;i++){
var row = rows[i];//循环每一行
totalNum += row.num;
totalAmount += row.amount;
}
return value + ' - ' + rows.length + ' 条数据' +" <span style='color:green;'>"+totalNum+"件商品</span>" +"<span style='color:#6b3980;'>总金额:"+totalAmount+"</span>";
} })
;})
;

 

 

 

 初始化状态:

 

 

 

 

 饼状图根据查询传递的参数进行拼装sqpl语句:

 

public String getWhereSql(){

String sql = "";

if(beginDate != null && !"".equals(beginDate)){
sql += " and b.vdate >= ?";
params.add(beginDate);
}

if(endDate != null && !"".equals(endDate)){
sql += " and b.vdate < ?";
params.add(endDate);
}

if(status != null && !"".equals(status)){
sql += " and b.status = ?";
params.add(status);
}

return sql.replace("and", "where");

}

public List getParams() {
return params;
}

public void setParams(List params) {
this.params = params;
}

 

 饼状图效果图:

 

 

 

 

 

posted on 2019-08-17 19:40  悠悠紫荆  阅读(263)  评论(0编辑  收藏  举报

导航