需求在这


客户拜访模块:
新增客户拜访和客户拜访列表
多对的关系,被拆成了两个一对多,自己定义客户拜访表
并且此模块改用注解方式来编码
<!-- 开启注解的扫描 -->
<context:component-scan base-package="com.itheima"/><!-- 扫描包下所有文件 -->
麻烦点:多对多的处理、SSH注解方式下sessionFactory的注入

综合分析:
客户来源统计
麻烦点:HQL的多表查询

用户拦截:登录验证

DAO

CustomerDaoImpl.java

package com.itheima.dao;import java.util.List;import com.itheima.domain.Customer;/*** 客户的持久层* @author 寒面银枪* 2019年7月2日-下午8:22:52*/                                           //继承的时候传递了正确的类型就行了
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {/*基本的增删改查都不用写了  BaseDaoImpl根据泛型已经都实现了通用的方法 *//*** 查询对应的来源(网络营销、电话营销分别有几个人)*/@Overridepublic List<Object[]> findBySource() {// 定义HQL// SELECT * FROM cst_customer c,base_dict d WHERE d.dict_id = c.cust_source// 分组查询 SELECT * FROM cst_customer c,base_dict d WHERE d.dict_id = c.cust_source group by d.dict_id// 查询内容:SELECT d.dict_item_name,count(*) FROM cst_customer c,base_dict d WHERE d.dict_id = c.cust_source group by d.dict_idString hql = "select c.source.dict_item_name,count(*) from Customer c inner join c.source group by c.source";// 查询return (List<Object[]>) this.getHibernateTemplate().find(hql);}}

VisitDaoImpl.java

package com.itheima.dao;import javax.annotation.Resource;import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;import com.itheima.domain.Visit;/*** 客户拜访的持久层* @author 寒面银枪* 2019年7月7日-下午2:53:31*/
@Repository(value="visitDao")
public class VisitDaoImpl extends BaseDaoImpl<Visit> implements VisitDao {//实现dao别忘了/** 注意:注入sessionfactory本来应该在父类BaseDaoImpl中写的  但由于之前都是配置文件方式,不好破坏BaseDaoImpl的结构,就直接在这里写了*///注入sessionfactory/*@Resource(name="sessionFactory")private SessionFactory sessionFactory;   不行 报错 无法修改HibernateDaoSupprot中的sessionfactory属性进行注解原因:父类HibernateDaoSupport的setSessionFacoty方法没有加注解@Autowired或者@Resource spring无法自动注入mybatis的setSqlSessionFacoty方法就加了注解 避免了这个麻烦的问题*/@Resource(name="sessionFactory")  //本来就在IOC的配置文件里 不怕,能直接拿到  内存(IOC容器)中有名称为sessionFactory的对象就注入public void set2SessionFactory(SessionFactory sessionFactory) {//关键 调用父类的set方法注入sessionFactorysuper.setSessionFactory(sessionFactory);}/*//网上号称最简单的方式@Autowired  按类型自动装配,只要内存中有sessionFactory对象  显然不如上面按名称注入的好public void setMySessionFactory(SessionFactory sessionFactory){  super.setSessionFactory(sessionFactory);  }  */}

domain

Customer.java

package com.itheima.domain;import java.util.HashSet;
import java.util.Set;import com.alibaba.fastjson.annotation.JSONField;public class Customer {private Long cust_id;//客户名称private String cust_name;//客户姓名private Long cust_user_id;//负责人idprivate Long cust_create_id;//创建人id 这两个暂时不管/*private String cust_source;//客户来源private String cust_industry;//客户所属行业(eg:客户来自于百度  那么行业可以是互联网)private String cust_level;//客户级别*/   private String cust_linkman;//联系人private String cust_phone;//固定电话private String cust_mobile;//移动电话//一对多 多方写对象   那么上面普通字段的写法就要注释掉了//一:客户来源  多:客户private Dict source; //一:客户行业  多:客户private Dict industry;//一:客户级别  多:客户private Dict level;// 上传文件保存的路径private String filepath;/*** 和联系人配置一对多  (我:百度公司 有多个联系人:CEO、CFO等等...)* * customer(1)和linkman(多)       同样一方可以不写集合(此处还是写了,为了演示问题) 全部交给有外键的多方去配,有双方有一方维护外键就够了*   客户写了联系人   联系人又写了客户  双方互相包含 真的会出现很多问题,不如不写呢  一方维护就行了呗*/@JSONField(serialize=false)  //必须禁止set转json 否则就是死循环private Set<Linkman> linkmans=new HashSet<Linkman>();//一方这次似乎真的放弃的 都给多方去维护  不写多方的中间表了public Long getCust_id() {return cust_id;}public void setCust_id(Long cust_id) {this.cust_id = cust_id;}public String getCust_name() {return cust_name;}public void setCust_name(String cust_name) {this.cust_name = cust_name;}public Long getCust_user_id() {return cust_user_id;}public void setCust_user_id(Long cust_user_id) {this.cust_user_id = cust_user_id;}public Long getCust_create_id() {return cust_create_id;}public void setCust_create_id(Long cust_create_id) {this.cust_create_id = cust_create_id;}public String getCust_linkman() {return cust_linkman;}public void setCust_linkman(String cust_linkman) {this.cust_linkman = cust_linkman;}public String getCust_phone() {return cust_phone;}public void setCust_phone(String cust_phone) {this.cust_phone = cust_phone;}public String getCust_mobile() {return cust_mobile;}public void setCust_mobile(String cust_mobile) {this.cust_mobile = cust_mobile;}public Dict getSource() {return source;}public void setSource(Dict source) {this.source = source;}public Dict getIndustry() {return industry;}public void setIndustry(Dict industry) {this.industry = industry;}public Dict getLevel() {return level;}public void setLevel(Dict level) {this.level = level;}public String getFilepath() {return filepath;}public void setFilepath(String filepath) {this.filepath = filepath;}public Set<Linkman> getLinkmans() {return linkmans;}public void setLinkmans(Set<Linkman> linkmans) {this.linkmans = linkmans;}}

Customer.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.itheima.domain.Customer" table="cst_customer"><id name="cust_id" column="cust_id"><generator class="native"/></id><property name="cust_name" column="cust_name"/><property name="cust_user_id" column="cust_user_id"/><property name="cust_create_id" column="cust_create_id"/><!-- <property name="cust_source" column="cust_source"/><property name="cust_industry" column="cust_industry"/><property name="cust_level" column="cust_level"/> --><property name="cust_linkman" column="cust_linkman"/><property name="cust_phone" column="cust_phone"/><property name="cust_mobile" column="cust_mobile"/><!-- 上传文件保存的路径  --><property name="filepath" column="filepath"/> <!-- 不配置长度就是默认长度 --><!-- 一对多  配置多方 本类的全限定名已经知道了  这里配的应该就是另一方javaBean的全路径了name:当前(多方)javaBean属性    class:关联的另一方(一方)类的全路径   column:表中外键字段名称-->      <many-to-one name="source" class="com.itheima.domain.Dict" column="cust_source"/><many-to-one name="industry" class="com.itheima.domain.Dict" column="cust_industry"/><many-to-one name="level" class="com.itheima.domain.Dict" column="cust_level"/><!-- customer(一)和Linkman(多)一对多   本来不用配置 为了显示问题而配置的 --><set name="linkmans" inverse="true"> <!--一方放弃外键维护 一方维护所有对应的多方很累  双方有一方维护就够了 必须有一方放弃维护 --><key column="lkm_cust_id"/><!-- 外键名称 --><one-to-many class="com.itheima.domain.Linkman"/></set></class></hibernate-mapping>    

Visit.java

package com.itheima.domain;/*** 客户拜访的javaBean* @author 寒面银枪* 2019年7月7日-下午2:14:47*/
public class Visit {/***   `visit_id` VARCHAR(32) NOT NULL,`visit_cust_id` BIGINT(32) DEFAULT NULL COMMENT '客户id',`visit_user_id` BIGINT(32) DEFAULT NULL COMMENT '负责人id',`visit_time` VARCHAR(32) DEFAULT NULL COMMENT '拜访时间',`visit_interviewee` VARCHAR(32) DEFAULT NULL COMMENT '被拜访人',`visit_addr` VARCHAR(128) DEFAULT NULL COMMENT '拜访地点',`visit_detail` VARCHAR(256) DEFAULT NULL COMMENT '拜访详情',`visit_nexttime` VARCHAR(32) DEFAULT NULL COMMENT '下次拜访时间',*/private String visit_id;//主键private String visit_time;//拜访时间private String visit_interviewee;//被拜访的人private String visit_addr;//拜访地点private String visit_detail;//拜访详情private String visit_nexttime;//下次拜访时间//外键 和客户  (中间表都是多方  多方对一方,一个对象)private Customer customer;//外键 和用户private User user;public String getVisit_id() {return visit_id;}public void setVisit_id(String visit_id) {this.visit_id = visit_id;}public String getVisit_time() {return visit_time;}public void setVisit_time(String visit_time) {this.visit_time = visit_time;}public String getVisit_interviewee() {return visit_interviewee;}public void setVisit_interviewee(String visit_interviewee) {this.visit_interviewee = visit_interviewee;}public String getVisit_addr() {return visit_addr;}public void setVisit_addr(String visit_addr) {this.visit_addr = visit_addr;}public String getVisit_detail() {return visit_detail;}public void setVisit_detail(String visit_detail) {this.visit_detail = visit_detail;}public String getVisit_nexttime() {return visit_nexttime;}public void setVisit_nexttime(String visit_nexttime) {this.visit_nexttime = visit_nexttime;}public Customer getCustomer() {return customer;}public void setCustomer(Customer customer) {this.customer = customer;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}}

Visit.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping><class name="com.itheima.domain.Visit" table="sale_visit"><id name="visit_id" column="visit_id"><generator class="uuid"/></id><property name="visit_time" column="visit_time"/><property name="visit_interviewee" column="visit_interviewee"/><property name="visit_addr" column="visit_addr"/><property name="visit_detail" column="visit_detail"/><property name="visit_nexttime" column="visit_nexttime"/><!-- 先配置多方 name 当前JavaBean中的属性class 属性的全路径(当然是name属性对应的了)column 外键的字段--><many-to-one name="customer" class="com.itheima.domain.Customer" column="visit_cust_id"/><many-to-one name="user" class="com.itheima.domain.User" column="visit_user_id"/><!-- 写完一个新的hbm.xml千万别忘记在applicationContext.xml中引入 --></class></hibernate-mapping>

Service

CustomerServiceImpl.java

package com.itheima.service;import java.util.List;import org.hibernate.criterion.DetachedCriteria;
import org.springframework.transaction.annotation.Transactional;import com.itheima.dao.CustomerDao;
import com.itheima.domain.Customer;
import com.itheima.domain.PageBean;/*** 客户的业务层* @author 寒面银枪  * 2019年7月2日-下午7:06:18*/
@Transactional //下面的方法就都有了事务
public class CustomerServiceImpl implements CustomerService {private CustomerDao customerDao;public void setCustomerDao(CustomerDao customerDao) {this.customerDao = customerDao;}/*** 保存客户*/public void save(Customer customer) {customerDao.save(customer);}/*** 分页查询*/@Overridepublic PageBean<Customer> findByPage(Integer pageCode, Integer pageSize, DetachedCriteria criteria) {return customerDao.findByPage(pageCode,pageSize,criteria);}/*** 通过主键查询客户*/@Overridepublic Customer findById(Long cust_id) {return customerDao.findById(cust_id);}/*** 删除客户*/@Overridepublic void delete(Customer customer) {customerDao.delete(customer);}/*** 更新客户*/@Overridepublic void update(Customer customer) {customerDao.update(customer);}/*** 查询所有客户*/@Overridepublic List<Customer> findAll() {return customerDao.findAll();}/*** 统计来源客户的数量*/@Overridepublic List<Object[]> findBySource() {return customerDao.findBySource();}}

VisitServiceImpl.java

package com.itheima.service;import javax.annotation.Resource;import org.hibernate.criterion.DetachedCriteria;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import com.itheima.dao.VisitDao;
import com.itheima.domain.PageBean;
import com.itheima.domain.Visit;@Service(value="visitService")
@Transactional
public class VisitServiceImpl implements VisitService {@Resource(name="visitDao")private VisitDao visitDao;/*** 分页查询*/@Overridepublic PageBean<Visit> findByPage(Integer pageCode, Integer pageSize, DetachedCriteria criteria) {return visitDao.findByPage(pageCode, pageSize, criteria);}/*** 保存拜访记录*/@Overridepublic void save(Visit visit) {visitDao.save(visit);}
}

Action

CustomerAction.java

package com.itheima.web.action;import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;import com.itheima.domain.Customer;
import com.itheima.domain.Dict;
import com.itheima.domain.PageBean;
import com.itheima.service.CustomerService;
import com.itheima.utils.FastJsonUtil;
import com.itheima.utils.UploadUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;/*** 客户的控制层(web层)* @author 寒面银枪* 2019年7月4日-下午2:45:06*/
public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{private static final long serialVersionUID = 1L;/*** 以后除非接收的单个参数使用属性驱动 否则都使用模型驱动封装数据 实现ModelDriven接口* 多简单:实现接口 写一个javaBean属性 接口必须实现的方法内返回对象  即可*/private Customer customer=new Customer();//必须手动实例化//类的属性是由get和set方法决定的 与字段无关  所以Action类有一个属性modelpublic Customer getModel() {return customer;}//注入service 提供service成员属性private CustomerService customerService;public void setCustomerService(CustomerService customerService) {this.customerService = customerService;}//一旦Action给spring管理  Struts的自动注入就失效了  必须手动注入  既然Action在spring的xml中了  那么多配置一个属性就是了/*** 保存客户的方法* @return*/public String add() {System.out.println("web层保存客户...");customerService.save(customer);return NONE;}//属性驱动的方式封装当前页  默认值是1private Integer pageCode=1;public void setPageCode(Integer pageCode) {if(pageCode==null) pageCode=1;this.pageCode = pageCode;}//每页显示的数据的条数  (如果可以让用户选择,那么就不能写死了)private Integer pageSize=2;//默认2条public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}/*** 分页查询*/public String findByPage() {//调用service  web层可以提前拼条件了DetachedCriteria criteria=DetachedCriteria.forClass(Customer.class);//注意不是写PageBean.class 查询谁写谁//条件查询 多加几行拼条件的代码就行了//拼接客户名称String cust_name = customer.getCust_name();if(cust_name!=null&&!cust_name.trim().isEmpty()) {criteria.add(Restrictions.like("cust_name", "%"+cust_name+"%"));}//拼接客户级别Dict level = customer.getLevel();if(level!=null&&!level.getDict_id().trim().isEmpty()) {criteria.add(Restrictions.eq("level.dict_id",level.getDict_id()));//后台也可以直接写level.dict_id  框架就是好啊}//拼接客户来源Dict source = customer.getSource();if(source!=null&&!source.getDict_id().trim().isEmpty()) {criteria.add(Restrictions.eq("source.dict_id",source.getDict_id()));}//查询  默认不封装条件 就是查询所有PageBean<Customer> page = customerService.findByPage(pageCode,pageSize,criteria);//压栈  //先获取值栈ValueStack vs = ActionContext.getContext().getValueStack();//栈顶是map<"page",page>vs.set("page", page);/*** 若是对象用push方法,因为在栈顶,对象名都可以省略不写最简单* 若是集合用set方法 ,最为方便  list[0].username   jstl:foreach表达式一循环  u.username更简单了*/return "page";}/*** 初始化到添加的页面* @return*/public String initAddUI() {return "initAddUI";}/*** 文件的上传,需要在Action类中提供成员属性,属性的命名是有规则的!!* private File upload;  //类型File固定的  属性名必须和前端的name属性值一模一样    此属性表示要上传的文件* private String uploadFileName; //前一半"upload"是前端的name值 后一半的"FileName"固定  表示上传文件的名称,且不会出现中文乱码* private String uploadContentType;//前一半"upload"是前端的name值 后一半"ContentType"固定  表示上传文件的MIME类型* 最后提供set方法 拦截器就会自动帮你注入值了 多好*/private File upload;//要上传的文件  关键是这个麻烦的玩意儿 帮你封装好了 太强了private String uploadFileName;//要上传的文件名private String uploadContentType;//要上传的文件类型public void setUpload(File upload) {this.upload = upload;}public void setUploadFileName(String uploadFileName) {this.uploadFileName = uploadFileName;}public void setUploadContentType(String uploadContentType) {this.uploadContentType = uploadContentType;}/*** 保存客户的方法* @return* @throws IOException */public String save() throws IOException {//处理文件上传if(uploadFileName!=null) {//说明用户选择了要上传的文件/*System.out.println("文件名:"+uploadFileName);System.out.println("文件类型:"+uploadContentType);*///把名称处理下 获得唯一名称  传入filename为了获取后缀名String uuidname=UploadUtils.getUUIDName(uploadFileName);//把文件上传到"E:\\Tomcat\\apache-tomcat-8.5.4\\webapps\\upload"//默认上传路径以静态常量的形式放在上传工具类中了//简单方式 新建一个文件 然后将封装的File upload文件copy到此新文件内File file=new File(UploadUtils.UPLOAD_PATH+uuidname);//上面加了"//" 此处拼接时就不用加了FileUtils.copyFile(upload, file);//导Apache.commons.io包/*三行可以封装成一行*/UploadUtils.upload(uploadFileName, upload);//上传文件路径记录在数据库customer.setFilepath(UploadUtils.UPLOAD_PATH+uuidname);//如果一直用这个模板 可以全部封装成工具类 一行代码实现上传  当然3行也不多}customerService.save(customer);return "save";}/*** 删除客户*/public String delete() {//删除客户//先获取客户上传文件的路径 将客户上传的文件全删了customer=customerService.findById(customer.getCust_id());//获取上传文件的路径String filepath=customer.getFilepath();//删除客户customerService.delete(customer);//再删除文件  很简单File file=new File(filepath);//先获取文件if(file.exists()) {file.delete();}return "delete";}/*** 跳转到初始修改页面*/public String initUpdate() {customer = customerService.findById(customer.getCust_id());//customer多例的 直接赋给customer没事   一次请求新new一个action/*压栈  但是注意 返回值赋给了customer 而customer是setModel方法的返回值 也即Action属性  而Action默认压栈 所以customer就在值栈内了,eg: model.cust_name就可以取得客户姓名*/return "initUpdate";}/*** 修改客户功能* @return* @throws IOException */public String update() throws IOException {//判断是否上传新图片  if(uploadFileName!=null) {//先删除旧图片//上面upload是上传组件file传过来的  下面的旧的路径名是隐藏域传递过来的String oldFilepath=customer.getFilepath();if(oldFilepath!=null&&!oldFilepath.trim().isEmpty()) {//说明旧的文件存在File oldfile=new File(oldFilepath);oldfile.delete();}//上传新图片String uuidName = UploadUtils.getUUIDName(uploadFileName);File file = new File(UploadUtils.UPLOAD_PATH+uuidName);FileUtils.copyFile(upload, file);//这个复制工具类是Apache的//把客户新图片的路径更新到数据库customer.setFilepath(UploadUtils.UPLOAD_PATH+uuidName);}//上面的{}内的逻辑应该是原子性的 所以应该封装到service层去做 (万一删完出错了..咋办) 不应该在web层做的  //任务 进一步封装上传工具类  封装edit方法 (update方法留着 因为通用)//更新客户的信息就ok了customerService.update(customer);return "update";}/*** 查询所有客户   Adjx请求  不用跳转* @return*/public String findAll() {List<Customer> list=customerService.findAll();//转换成jsonString jsonString = FastJsonUtil.toJSONString(list);FastJsonUtil.write_json(ServletActionContext.getResponse(), jsonString);return NONE;}/*** 统计来源客户的数量* @return*/public String findBySource() {List<Object[]> list=customerService.findBySource();//压栈ValueStack vs = ActionContext.getContext().getValueStack();//栈顶是map<"page",page>vs.set("sourcelist", list);return "findBySource";}}

VisitAction.java

package com.itheima.web.action;import javax.annotation.Resource;
import javax.annotation.Resources;import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;import com.itheima.domain.PageBean;
import com.itheima.domain.User;
import com.itheima.domain.Visit;
import com.itheima.service.VisitService;/*** 客户拜访的控制器* @author 寒面银枪* 2019年7月7日-下午2:38:30*/
/*下面两行配置等价于<bean id="" class="com.itheima.web.action.VisitAction" scope="prototype"></bean>
*/
@Controller(value="visitAction")
@Scope(value="prototype")
public class VisitAction extends BaseAction<Visit>{private static final long serialVersionUID = -139853886677968072L;@Resource(name="visitService")  //按名称注入private VisitService visitService;//条件查询的起止日期private String beginDate;private String endDate;public void setBeginDate(String beginDate) {this.beginDate = beginDate;}public void setEndDate(String endDate) {this.endDate = endDate;}//也提供get方法 方便前台获取值public String getBeginDate() {return beginDate;}public String getEndDate() {return endDate;}/*** 分页查询:* 查询客户的拜访记录,根据用户的主键查询 (客户Customer拜访用户user)* select * from sale_visit where visit_user_id = ?* @return*/public String findByPage() {//先获取当前登录的用户User user= (User) getSession().getAttribute("user");//判断 虽然..但是养成好习惯呗if(user==null) {return LOGIN;}//查询该用户(其实是公司负责人)下所有拜访记录DetachedCriteria criteria=DetachedCriteria.forClass(Visit.class);//条件查询 筛选条件的拼接if(beginDate!=null&&!beginDate.trim().isEmpty()) {criteria.add(Restrictions.ge("visit_time", beginDate));}if(endDate!=null&&!endDate.trim().isEmpty()) {criteria.add(Restrictions.le("visit_time", endDate));}//添加查询的其他条件criteria.add(Restrictions.eq("user.user_id", user.getUser_id()));//分页查询PageBean<Visit> page = visitService.findByPage(this.getPageCode(),this.getPageSize(),criteria);this.setVs("page", page);return "page";}/*** 新增拜访UI* @return*/public String initSave() {return "initSave";}/*** 保存拜访记录*/public String save() {//需要查到当前用户 一同存入数据库User user= (User) getSession().getAttribute("user");if(user==null) {return LOGIN;}getModel().setUser(user);//保存数据visitService.save(getModel());return "save";}}

interceptor

UserInterceptor.java

package com.itheima.web.interceptor;import org.apache.struts2.ServletActionContext;import com.itheima.domain.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;/*** 用户拦截器 过滤没有登录的   * 判断用户是否登录*     若登录:执行下一个拦截器*   否则:返回到登录页面(注意有些页面要放行,login和regist)* * 继承指定拦截器* @author 寒面银枪* 2019年7月7日-下午6:02:19*/
public class UserInterceptor extends MethodFilterInterceptor{private static final long serialVersionUID = -733814691331866464L;/*** 拦截目标Action方法*/protected String doIntercept(ActionInvocation invocation) throws Exception {//获取sessionUser user=(User)ServletActionContext.getRequest().getSession().getAttribute("user");if(user==null) {return "login";}//执行下一个拦截器return invocation.invoke();}}

xml

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"><!-- 配置Action -->
<struts><!-- 配置拦截器 --><!-- 设置常量 --><!-- 设置上传文件总大小的上限 默认值是2M struts.multipart.maxSize=2097152 (单个文件大小也可以设置)--><constant name="struts.multipart.maxSize" value="209715200"/> <!-- 加两个0 变200M --><!-- 先配置包结构 --><package name="crm" namespace="/" extends="struts-default"><interceptors><interceptor name="userInterceptor" class="com.itheima.web.interceptor.UserInterceptor"/></interceptors><!-- 配置全局结果页面 --><global-results><result name="login" type="redirect">/login.jsp</result></global-results><!-- Action由spring来管理,那么此处的class属性只写spring中的id值即可 --><action name="customer_*" class="customerAction" method="{1}"><!-- type默认请求转发 --><result name="page">/jsp/customer/list.jsp</result><result name="initAddUI">/jsp/customer/add.jsp</result><!-- 客户保存(添加)成功 需要转到客户列表查看 也即要转到另一个action   注意转到的action没有/  ".action"也可以省略也可以写--><result name="save" type="redirectAction">customer_findByPage</result><!-- 文件上传错误 文件过大 --><result name="input">/jsp/error.jsp</result><result name="delete" type="redirectAction">customer_findByPage.action</result><!-- 只能转发 千万不要重定向  重定向是一次新请求 值栈会清空的 --><result name="initUpdate">/jsp/customer/edit.jsp</result><result name="update" type="redirectAction">customer_findByPage.action</result><result name="findBySource">/jsp/totals/sources.jsp</result><interceptor-ref name="userInterceptor"/><!-- 引入默认拦截器栈 修改上传文件类型 --><interceptor-ref name="defaultStack"><!-- 设置fileUpload拦截器的allowedExtensions属性  能决定上传文件的类型--><param name="fileUpload.allowedExtensions">.jpg,.txt</param><!-- 设置单个上传文件的大小  也是200M--><param name="fileUpload.maximumSize">209715200</param></interceptor-ref></action><!-- 用户模块 --><action name="user_*" class="userAction" method="{1}"><result name="loginOK" type="redirect">/index.jsp</result><interceptor-ref name="userInterceptor"><!-- 放行 --><param name="excludeMethods">login,regist,checkCode</param></interceptor-ref><interceptor-ref name="defaultStack"/></action><!--字典模块 --><action name="dict_*" class="dictAction" method="{1}"><interceptor-ref name="userInterceptor"/><interceptor-ref name="defaultStack"/></action><!--联系人模块 --><action name="linkman_*" class="linkmanAction" method="{1}"><result name="page">/jsp/linkman/list.jsp</result><result name="initAddUI">/jsp/linkman/add.jsp</result><result name="save" type="redirectAction">linkman_findByPage.action</result><result name="delete" type="redirectAction">linkman_findByPage.action</result><result name="initUpdate">/jsp/linkman/edit.jsp</result><result name="update" type="redirectAction">linkman_findByPage.action</result><interceptor-ref name="userInterceptor"/><interceptor-ref name="defaultStack"/></action><!-- 客户拜访模块 --><action name="visit_*" class="visitAction" method="{1}"><result name="page">/jsp/visit/list.jsp</result><result name="initSave">/jsp/visit/add.jsp</result><result name="save" type="redirectAction">visit_findByPage.action</result><interceptor-ref name="userInterceptor"/><interceptor-ref name="defaultStack"/></action></package></struts>

applicationContext.xml

<?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: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.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 整合Hibernate方式2:将hibernate.cfg.xml的配置完全转移到这里来 --><!-- 先配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"/><property name="jdbcUrl" value="jdbc:mysql:///crm_28"/><property name="user" value="root"/><property name="password" value="1111"/></bean><!-- 拜访模块开始,使用注解方式写 --><!-- 开启注解的扫描 --><context:component-scan base-package="com.itheima"/><!-- 扫描包下所有文件 --><!-- 编写一个名称固定的bean(spring提供的) 帮我们加载hibernate.cfg.xml的配置文件这一个类一加载完,配置文件就加载完了  sessionFactory也创建好了   sessionFactory是重量级的,不能轻易销毁和创建,正好springIOC默认就是单例的--><!-- 使用LocalSessionFactoryBean加载配置 可以将一些hibernate.cfg.xml的配置移到此处的属性里 --><bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!-- 先加载连接池 --><property name="dataSource" ref="dataSource"/><!-- 加载方言 加载可选项 --><property name="hibernateProperties"><!-- 里面配属性文件 写法有点不一样 --><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.format_sql">true</prop><prop key="hibernate.hbm2ddl.auto">update</prop> <!-- 没有表时帮忙生成表 --></props></property><!-- 最后引入映射的配置文件 --><property name="mappingResources"><list><value>com/itheima/domain/User.hbm.xml</value><value>com/itheima/domain/Customer.hbm.xml</value> <!-- 写好了javaBean别忘记引入  让表自动生成 比较容易发现有没有少配置--><value>com/itheima/domain/Dict.hbm.xml</value><value>com/itheima/domain/Linkman.hbm.xml</value><value>com/itheima/domain/Visit.hbm.xml</value></list></property></bean><!-- 事务模块 --><!-- 先配置平台事务管理器 --><bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"><!--昨天传入连接池 今天就传入sessionFactory  session能管理事务  --><property name="sessionFactory" ref="sessionFactory"/></bean><!-- 开启事务注解 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 配置客户模块 --><bean id="customerAction" class="com.itheima.web.action.CustomerAction" scope="prototype"><property name="customerService" ref="customerService"/></bean><bean id="customerService" class="com.itheima.service.CustomerServiceImpl"><property name="customerDao" ref="customerDao"/></bean><bean id="customerDao" class="com.itheima.dao.CustomerDaoImpl"><property name="sessionFactory" ref="sessionFactory"></property></bean> <!-- 配置用户模块  注意Action必须多例--><bean id="userAction" class="com.itheima.web.action.UserAction" scope="prototype"><property name="userService" ref="userService"/><!-- 手动注入service 其实就是注入一个属性 --></bean><bean id="userService" class="com.itheima.service.UserServiceImpl"><property name="userDao" ref="userDao"/></bean><bean id="userDao" class="com.itheima.dao.UserDaoImpl"><!-- 立刻意识到service里要注入dao --><property name="sessionFactory" ref="sessionFactory"/></bean><!-- 配置字典类--> <!-- 配置Action千万注意是多例的 又忘记了,唉! --><bean id="dictAction" class="com.itheima.web.action.DictAction" scope="prototype"><property name="dictService" ref="dictService"/></bean><bean id="dictService" class="com.itheima.service.DictServiceImpl"><property name="dictDao" ref="dictDao"/></bean><bean id="dictDao" class="com.itheima.dao.DictDaoImpl"><property name="sessionFactory" ref="sessionFactory"/></bean><!-- <bean id="" class="org.apache.struts2.interceptor.FileUploadInterceptor"></bean> --><!-- 配置linkman模块--><!--  Action的 scope又忘了  --><bean id="linkmanAction" class="com.itheima.web.action.LinkmanAction" scope="prototype"><property name="linkmanService" ref="linkmanService"/></bean><bean id="linkmanService" class="com.itheima.service.LinkmanServiceImpl"><property name="linkmanDao" ref="linkmanDao"/></bean><bean id="linkmanDao" class="com.itheima.dao.LinkmanDaoImpl"><property name="sessionFactory" ref="sessionFactory"/></bean></beans>

jsp

list.jsp(visit)

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<TITLE>联系人列表</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK href="${pageContext.request.contextPath }/css/Style.css" type=text/css rel=stylesheet>
<LINK href="${pageContext.request.contextPath }/css/Manage.css" type=text/cssrel=stylesheet>
<%-- <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.11.3.min.js"></script> 高版本的jquery,会使日期控件失效
--%><!-- 日期插件,使用jquery -->
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery-1.4.2.js"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath }/jquery/jquery.datepick.css" type="text/css">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick-zh-CN.js"></script><SCRIPT language=javascript>function to_page(page){if(page){$("#page").val(page);}document.customerForm.submit();}$(function(){//给beginDate和endDate绑定日期控件的方法$('#beginDate').datepick({dateFormat: 'yy-mm-dd'}); $('#endDate').datepick({dateFormat: 'yy-mm-dd'}); });</SCRIPT><META content="MSHTML 6.00.2900.3492" name=GENERATOR>
</HEAD>
<BODY><FORM id="customerForm" name="customerForm"action="${pageContext.request.contextPath }/visit_findByPage.action"method=post><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_019.jpg"border=0></TD><TD width="100%" background="${pageContext.request.contextPath }/images/new_020.jpg"height=20></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_021.jpg"border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15 background="${pageContext.request.contextPath }/images/new_022.jpg"><IMGsrc="${pageContext.request.contextPath }/images/new_022.jpg" border=0></TD><TD vAlign=top width="100%" bgColor=#ffffff><TABLE cellSpacing=0 cellPadding=5 width="100%" border=0><TR><TD class=manageHead>当前位置:客户拜访管理 &gt; 客户拜访列表</TD></TR><TR><TD height=2></TD></TR></TABLE><TABLE borderColor=#cccccc cellSpacing=0 cellPadding=0width="100%" align=center border=0><TBODY><TR><TD height=25><TABLE cellSpacing=0 cellPadding=2 border=0><TBODY><TR><TD>联系人名称:</TD><TD><INPUT class=textbox id=sChannel2 style="WIDTH: 80px" maxLength=50 name="lkm_name" value="${model.user.lkm_name }"></TD><TD>选择日期:</TD><TD><INPUT class=textbox id="beginDate" style="WIDTH: 80px" maxLength=50 name="beginDate" value="${beginDate }">至<INPUT class=textbox id="endDate" style="WIDTH: 80px" maxLength=50 name="endDate" value="${endDate }"></TD><TD><INPUT class=button id=sButton2 type=submitvalue=" 筛选 " name=sButton2></TD></TR></TBODY></TABLE></TD></TR><TR><TD><TABLE id=gridstyle="BORDER-TOP-WIDTH: 0px; FONT-WEIGHT: normal; BORDER-LEFT-WIDTH: 0px; BORDER-LEFT-COLOR: #cccccc; BORDER-BOTTOM-WIDTH: 0px; BORDER-BOTTOM-COLOR: #cccccc; WIDTH: 100%; BORDER-TOP-COLOR: #cccccc; FONT-STYLE: normal; BACKGROUND-COLOR: #cccccc; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #cccccc"cellSpacing=1 cellPadding=2 rules=all border=0><TBODY><TRstyle="FONT-WEIGHT: bold; FONT-STYLE: normal; BACKGROUND-COLOR: #eeeeee; TEXT-DECORATION: none"><TD>拜访客户</TD><TD>拜访时间</TD><TD>被拜访人</TD><TD>拜访地点</TD><TD>拜访详情</TD><TD>下次拜访时间</TD></TR><c:forEach items="${page.beanList}" var="visit"><TRstyle="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"><TD>${visit.customer.cust_name }</TD><TD>${visit.visit_time }</TD><TD>${visit.visit_interviewee }</TD><TD>${visit.visit_addr }</TD><TD>${visit.visit_detail }</TD><TD>${visit.visit_nexttime }</TD></TR></c:forEach></TBODY></TABLE></TD></TR><TR><TD><!-- 使用静态引入 --><%@ include file="/jsp/page.jsp" %></TD></TR></TBODY></TABLE></TD><TD width=15 background="${pageContext.request.contextPath }/images/new_023.jpg"><IMGsrc="${pageContext.request.contextPath }/images/new_023.jpg" border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_024.jpg"border=0></TD><TD align=middle width="100%"background="${pageContext.request.contextPath }/images/new_025.jpg" height=15></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_026.jpg"border=0></TD></TR></TBODY></TABLE></FORM>
</BODY>
</HTML>

add.jsp(visit)

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<TITLE>添加客户拜访</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK href="${pageContext.request.contextPath }/css/Style.css" type=text/css rel=stylesheet>
<LINK href="${pageContext.request.contextPath }/css/Manage.css" type=text/css rel=stylesheet>
<META content="MSHTML 6.00.2900.3492" name=GENERATOR><!-- 日期插件,使用jquery -->
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery-1.4.2.js"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath }/jquery/jquery.datepick.css" type="text/css">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick-zh-CN.js"></script><script type="text/javascript">$(function(){//使用class属性处理  'yy-mm-dd' 设置格式"yyyy/mm/dd"   如此便设置了日期格式框$('#timeId').datepick({dateFormat: 'yy-mm-dd'}); $('#nextTimeId').datepick({dateFormat: 'yy-mm-dd'}); //获取所有客户var url="${pageContext.request.contextPath }/customer_findAll.action";$.post(url,function(data){$(data).each(function(){$('#customerId').append("<option value='"+this.cust_id+"'>"+this.cust_name+"</option>");});});});
</script></HEAD>
<BODY><FORM id=form1 name=form1 action="${pageContext.request.contextPath }/visit_save.action" method=post><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_019.jpg"border=0></TD><TD width="100%" background="${pageContext.request.contextPath }/images/new_020.jpg"height=20></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_021.jpg"border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15 background=${pageContext.request.contextPath }/images/new_022.jpg><IMGsrc="${pageContext.request.contextPath }/images/new_022.jpg" border=0></TD><TD vAlign=top width="100%" bgColor=#ffffff><TABLE cellSpacing=0 cellPadding=5 width="100%" border=0><TR><TD class=manageHead>当前位置:客户拜访管理 &gt; 添加客户拜访</TD></TR><TR><TD height=2></TD></TR></TABLE><TABLE cellSpacing=0 cellPadding=5  border=0><tr><td>客户名称:</td><td><select name="customer.cust_id" id="customerId" style="WIDTH: 180px"></select></td><td>拜访时间:</td><td><INPUT class=textbox id="timeId" style="WIDTH: 180px" name="visit_time" readonly="readonly"></td></tr><TR><td>被拜访人:</td><td><INPUT class=textbox style="WIDTH: 180px" maxLength=50 name="visit_interviewee"></td><td>拜访地点:</td><td><INPUT class=textbox style="WIDTH: 180px" maxLength=50 name="visit_addr"></td></TR><TR><td>下次拜访时间 :</td><td><INPUT class=textbox id="nextTimeId" style="WIDTH: 180px" maxLength=50 name="visit_nexttime"></td></TR><TR>   <td>拜访详情 :</td><td><textarea rows="5" cols="26" name="visit_detail"></textarea></td></TR><tr><td rowspan=2><INPUT class=button id=sButton2 type=submitvalue="保存 " name=sButton2></td></tr></TABLE></TD><TD width=15 background="${pageContext.request.contextPath }/images/new_023.jpg"><IMG src="${pageContext.request.contextPath }/images/new_023.jpg" border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_024.jpg"border=0></TD><TD align=middle width="100%"background="${pageContext.request.contextPath }/images/new_025.jpg" height=15></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_026.jpg"border=0></TD></TR></TBODY></TABLE></FORM>
</BODY>
</HTML>

sources.jsp(totals)

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<TITLE>统计信息</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK href="${pageContext.request.contextPath }/css/Style.css" type=text/css rel=stylesheet>
<LINK href="${pageContext.request.contextPath }/css/Manage.css" type=text/cssrel=stylesheet>
<%-- <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.11.3.min.js"></script> 高版本的jquery,会使日期控件失效
--%><!-- 日期插件,使用jquery -->
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery-1.4.2.js"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath }/jquery/jquery.datepick.css" type="text/css">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery/jquery.datepick-zh-CN.js"></script><SCRIPT language=javascript>function to_page(page){if(page){$("#page").val(page);}document.customerForm.submit();}$(function(){//给beginDate和endDate绑定日期控件的方法$('#beginDate').datepick({dateFormat: 'yy-mm-dd'}); $('#endDate').datepick({dateFormat: 'yy-mm-dd'}); });</SCRIPT><META content="MSHTML 6.00.2900.3492" name=GENERATOR>
</HEAD>
<BODY><FORM id="customerForm" name="customerForm"action="${pageContext.request.contextPath }/visit_findByPage.action"method=post><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_019.jpg"border=0></TD><TD width="100%" background="${pageContext.request.contextPath }/images/new_020.jpg"height=20></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_021.jpg"border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15 background="${pageContext.request.contextPath }/images/new_022.jpg"><IMGsrc="${pageContext.request.contextPath }/images/new_022.jpg" border=0></TD><TD vAlign=top width="100%" bgColor=#ffffff><TABLE cellSpacing=0 cellPadding=5 width="100%" border=0><TR><TD class=manageHead>当前位置:统计管理 &gt; 客户来源统计</TD></TR><TR><TD height=2></TD></TR></TABLE><TABLE borderColor=#cccccc cellSpacing=0 cellPadding=0width="100%" align=center border=0><TBODY><TR><TD><TABLE id=gridstyle="BORDER-TOP-WIDTH: 0px; FONT-WEIGHT: normal; BORDER-LEFT-WIDTH: 0px; BORDER-LEFT-COLOR: #cccccc; BORDER-BOTTOM-WIDTH: 0px; BORDER-BOTTOM-COLOR: #cccccc; WIDTH: 100%; BORDER-TOP-COLOR: #cccccc; FONT-STYLE: normal; BACKGROUND-COLOR: #cccccc; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #cccccc"cellSpacing=1 cellPadding=2 rules=all border=0><TBODY><TRstyle="FONT-WEIGHT: bold; FONT-STYLE: normal; BACKGROUND-COLOR: #eeeeee; TEXT-DECORATION: none"><TD>客户来源</TD><TD>客户人数</TD></TR><c:forEach items="${sourcelist}" var="obj"><TRstyle="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"><TD>${obj[0]}</TD><TD>${obj[1]}</TD></TR></c:forEach></TBODY></TABLE></TD></TR></TBODY></TABLE></TD><TD width=15 background="${pageContext.request.contextPath }/images/new_023.jpg"><IMGsrc="${pageContext.request.contextPath }/images/new_023.jpg" border=0></TD></TR></TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width="98%" border=0><TBODY><TR><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_024.jpg"border=0></TD><TD align=middle width="100%"background="${pageContext.request.contextPath }/images/new_025.jpg" height=15></TD><TD width=15><IMG src="${pageContext.request.contextPath }/images/new_026.jpg"border=0></TD></TR></TBODY></TABLE></FORM>
</BODY>
</HTML>

SSH实战 第四天 代码相关推荐

  1. 2021年大数据Spark(三十九):SparkStreaming实战案例四 窗口函数

    目录 SparkStreaming实战案例四 窗口函数 需求 代码实现 SparkStreaming实战案例四 窗口函数 需求 使用窗口计算: 每隔5s(滑动间隔)计算最近10s(窗口长度)的数据! ...

  2. Android项目实战(四):ViewPager切换动画(3.0版本以上有效果)

    原文:Android项目实战(四):ViewPager切换动画(3.0版本以上有效果) 学习内容来自"慕课网" 一般APP进去之后都会有几张图片来导航,这里就学习怎么在这张图片切换 ...

  3. 《spring实战第四版》的读书笔记

    <spring实战第四版>的读书笔记 1 概述 <Spring实战第四版>描述了Spring4架构的设计,看完了以后,最大感觉是Spring的IOC与aop理念实在是太强大了, ...

  4. OAuth2简易实战(四)-Github社交联合登录

    1. OAuth2简易实战(四)-Github社交联合登录 1.1. 用到的第三方插件 https://github.com/spring-projects/spring-social-github ...

  5. 关于liaoxuefeng的python3教程实战第四天

    关于liaoxuefeng的python3教程 实战第四天. 地址:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df ...

  6. php本地文件打包代码,PHP实战:几行代码轻松实现PHP文件打包下载zip

    <PHP实战:几行代码轻松实现PHP文件打包下载zip>要点: 本文介绍了PHP实战:几行代码轻松实现PHP文件打包下载zip,希望对您有用.如果有疑问,可以联系我们. PHP应用 //获 ...

  7. Docker从入门到实战(四)

    一步一步走,写小白都能看懂的文章,将持续更新中,敬请期待! Docker从入门到实战(四) Docker基础 一:Docker基本操作 一般情况安装Docker之后系统会自动创建一个Docker的用户 ...

  8. WCF开发实战系列四:使用Windows服务发布WCF服务

    WCF开发实战系列四:使用Windows服务发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇文章中我们通过编写的控制台程序或WinForm程序来为本 ...

  9. 大数据Spark(三十九):SparkStreaming实战案例四 窗口函数

    文章目录 SparkStreaming实战案例四 窗口函数 需求 代码实现 SparkStreaming实战案例四 窗口函数 需求

  10. 4. Python脚本学习实战笔记四 新闻聚合

    4. Python脚本学习实战笔记四 新闻聚合 本篇名言:"人言纷杂,保持自我:工作勤奋,娱乐适度:对待朋友,不玩心术:处理事务,不躁不怒:生活讲究,量入为出:知足常乐,一生幸福!" ...

最新文章

  1. Xmanager连接Linux 9的方法
  2. 讨论:有多少项目是因为程序的原因而失败的
  3. 微服务下的APM全链路监控
  4. python中的类和对象
  5. unity项目中使用BUGLY遇到的的几个问题
  6. 处理v-html的潜在XSS风险
  7. 廖雪峰Python教程-笔记
  8. 前端:Vue前端开发规范,值得收藏!
  9. Web开发人员的必备工具 - Emmet (Zen Coding)
  10. “滚蛋吧”扎克伯格!
  11. 地大计算机学院保研华科人数,2020年华中科技大学保研率是多少
  12. IntelliJ IDEA 自定义控制台输出多颜色格式功能 --- 安装Grep Console插件
  13. 机器学习--支持向量机(一)什么是支持向量机
  14. 20190613 一个SQL问题
  15. 自动格式化SQL工具推荐
  16. 在计算机里面建一个新的文档,电脑上的word怎么新建文档
  17. cac会议投稿难度大吗_英文(会议)论文投稿准备与流程
  18. 有什么软件可以免费下载歌曲?99%不知道这3款软件!
  19. 学计算机物理去戴维斯还是伦斯勒理工学院好,为什么伦斯勒理工学院评价那么高?...
  20. 自然语言处理(NLP):国内会议

热门文章

  1. 笔记本触摸板没有反应了
  2. QT串口助手设计流程(如何实现一个串口助手
  3. 二级域名 免费+免备案
  4. 找到解决办法了,特回来写总结,the import cannot be resolved问题可以通过以下方法解决
  5. 电动自行车新国标正式实施 二季度数码市场需求好转
  6. Google一些关键词的运用
  7. CIM技术 构建数字孪生的智慧城市
  8. python 确定字符互异
  9. 开放大学毕业生自我鉴定计算机,开放大学毕业自我鉴定4篇
  10. 如何更改Win8,8.1中文版到英文版,亲测!