赞
踩
开始时间:7月17日
(一)Web开发4层开发
(二)综合应用:
学编程,就要学以致用,否则学得再熟练也没有
(三)教学方式:26天(线下),打算20天做完。
做web项目开发(完全模拟企业开发),包装2到3年的开发经验。
(四)教学目的:
(五)软件公司的组织结构:
下面部门都和程序员相关
研发部:程序员,美工(前端,设计图片),DBA(数据库调优员)
测试部:测试工程师(测试每个版本,找出bug,记录bug,国内大多数都是黑盒测试,只看功能,不看代码,而白盒都看)
产品部:了解软件市场和业务(提需求)
实施部:部署服务器,了解软硬件服务器(兼职性)
运维部:懂服务器(一般在机房隔壁办公)
市场部:重要!负责去拉项目来做(工资高,有提成,找程序员做标书)
其他:人力部和财务部和程序员关系不大
(六)软件开发生命周期
1--
招标:政府和金融机构等,需要做哪些项目后,会发布招标(工期,投入等)
投标: 市场部做标书,和程序员沟通。然后投给招标
甲方:招标方
乙方:投标方
2--可行性分析:------------------------------ 可行性分析报告
技术总监或者架构师负责
技术(本公司技术能不能匹配要求)
经济(是否还需招程序员,招哪些层次的程序员)
(如果中标了,而可行性较低,可以转给外包公司(所以说,中标稳赚不赔))
3----需求分析:--------------------------------《需求文档》
产品经理进行分析,需要和客户沟通(需求调研,有可能和程序员一起去)
项目原型(美工做,完成通用的一些业务功能模块页面):去需要调研时,都是带项目原型去和客户沟通的(给客户看静态的页面,确定是否是这些需求),容易确定需求。
确定需求之后,写好需求文档,还需双方签字,才能进行开发。
4----分析与设计:
负责人是架构师或者项目经理,就相当于盖一个房子,里面负责设计图纸的建筑师。而这时候负责搬砖的工人还没有招进来,就相当于程序员,所以说程序员是“码农
5----架构设计:整体性设计(服务器,选用技术)-----------------------------------------架构师
物理架构设计:项目将来运行所在的硬件服务器,用的硬盘
应用服务器:(Tomcat(免费,中小企业使用),weblogic(收费,功能强大,支持javaee:13种协议),websphere(ibm,收费),jboss(redhat公司,收费),resin(微软))
数据库服务器:mysql(小巧灵活,免费),oracle(笨重,收费),DB2,sqlservet,达梦
逻辑架构设计:代码分层
技术选型:java,.net (微软) ,框架
6----项目设计:项目经理负责 -------------项目设计文档
物理模型设计(项目经理设计):哪些表,哪些字段,字符的类型和长度,以及表和表之间的关系。工具:powerdesigner ----.pdm(能转换成表sql语句)
逻辑模型设计(实际中,由程序员自己写):哪些类,哪些属性和方法,方法的参数和返回值,以及类和类之间的关系。 工具:rationnal rose---pdl
界面设计:企业级应用(朴素,用户群体固定,并发数有限),互联网应用(炫酷)
算法设计:复杂业务,企业级应用不特别在意算法设计,而互联网应用会经常涉及(高并发)
7--搭建开发环境:项目经理搭建
创建项目,添加jar包,添加配置文件,添加静态页面,添加公共类以及其他资源;能够正常启动运行
8-----编码实现:HR开始忙起来,去面试程序员。-----------注释文档
9-----测试:并不是完全开发完项目才开始测试,而是开发和测试同步进行,一般每周都会提交一个版本交给测试部测试,测试找到bug,放在bug记录平台,程序员再去修改自己的bug。----测试用例-----------------测试用例
10-----试运行:实施部帮客户或者客户找人去买对应性能的服务器。运行大概一周,没问题就可以去上线了。程序员开始逐渐转到下一个项目你 -----------使用手册
11------上线:--------实施文档
12----运维:软件周期一般最长在5年,就要下架了(随着使用,系统会变慢) --------运维手册
13----文档编纂:包含在整个开发过程,例如;需求文档,项目设计文档,可行性分析文档和注释文档。
servlet,jsp(jspl) springMVC
CRM项目的简介:Customer Relationship Management 客户关系管理系统
类别为企业级应用,传统应用。给销售或者贸易型公司使用,在市场,销售,服务各个环节中维护客户关系。
CRM项目的宗旨:增加新客户,留住老客户,把已有客户转化成忠诚客户。
CRM是一类项目,每种行业,需要的CRM的实现都不一样,因为业务不一样,本CRM是给一个大型的进出口贸易公司来使用的,做大宗商品的进出口贸易;商品受管制
CRM项目的核心业务:
系统管理功能:不是直接处理业务数据,为了保证业务管理的功能正常安全运行而设计的功能。例如:登录功能,安全退出,登录验证(给超级管理员,系统管理员用的)
业务管理功能:处理业务数据
市场活动:市场部,设计市场活动营销活动
线索:销售部(初级销售),增加线索
客户和联系人:销售部(高级销售),有效地区分和跟踪客户和联系人
交易:销售部(高级销售),更好地区分和统计交易的各个阶段
销售回放:客户部,妥善安排销售回访。主动提醒(防止客户忘记)
统计图表:管理层用,统计交易表中各个阶段数据量。
系统管理功能表:
tbl_user 用户表
tbl_dic_type 数据字典类型表
tbl_dic_value 数据字典值
业务管理功能相关表:
tbl_activity 市场活动表
tbl_activeity_remark 市场活动备注表
tbl_clue_activity_relation 线索和市场活动的关联关系表
tbl_clue 线索表
tbl_clue_remark 线索备注表
tbl_customer 客户表
tbl_customer_remark 客户备注表
tbl_contacts 联系人表
tbl_contacts_remark 联系人备注表
tbl_contacts_activity_relation 联系人和市场活动的关联关系表
tbl_tran 交易表
tbl_tran_history 交易历史表
tbl_tran_remark 交易备注表
tbl_task 任务表
在表中,如果有一组字段能够唯一确认一条记录,则可以把它们设计成表的主键。推荐使用一个字段做主键,而且推荐使用没有业务含义的字段做主键。比如:id等。主键字段的类型和长度由主键值的生成方式来决定:
用来确定表和表之间的关系
一张表A中的一条记录可以对应另一张表B中的多条记录;而另一张表B中的一条记录只能对应一张表A中的一个记录。例如:学生表(子表)和班级表(父表),一般多的那张表引用一的那个表的主键
添加记录:先添加父表记录,才能添加子表记录
删除记录:先删除子表记录,才能删除父表记录
内连接([inner] join on :外键不能为空):查询所有符合条件的数据,并且要求结果在两张表都有对应的
左外连接(left login on)(外键可以为空,按需求选择左还是右):查询左侧表中所有符合条件的数据,即使在右表中没有对应的数据,右外连接则相反(right login on)
*如果外键不能为空,优先使用内连接
*如果外键能为空,按需求选择左右外连接
一张表A中的一条记录可以对应另一张表B中的一条记录;而另一张表B中的一条记录对应另一张表A中的一个记录。例如:个人信息表和驾照表,可以使用共享主键(不经常用)
添加记录:先添加先产生的表的记录,后再添加后产生的表的记录
删除记录:先删除后后产生的表记录,在删除先产生的表记录
查询数据:无需进行连接查询
一般都是用:唯一外键。
一张表A中的一条记录可以对应另一张表B中的多条记录;而另一张表B中的一条记录对应另一张表A中的多个记录。例如:学生表和课程表。
添加记录:先添加父表记录,再添加子表记录(中间表)
删除记录:先删除子表(中间表)记录,再删除父表记录。
查询记录:可能会进行关联查询
借助中间表来维护关系
java
Date
数据库
date:只有日期
time:只有时间
datetime:日期和时间
基于以上格式转换问题,都直接按照字符串处理:
导入表sql,物理模型设计完成。
创建项目,创建工程:crm
设置编码格式:统一UTF-8
添加jar包依赖:需求文档上有(不需要背)
添加配置文件:不需要背,前期搭建环境时,需要用而已。
添加静态页面:防止非法访问,造成的恶意破坏,一般都把页面放在WEB-INF下
合理的项目文件目录:
生成的Tomcat服务器项目文件目录:
1.流程图
2.写代码,先写底层,再写高层(高层调用底层)
一个资源目录,创建一个controller进行响应
同步请求:页面全局刷新
异步请求:全局或者局部刷新都可以,存在两个刷新方式时,只能用异步请求。
一个表,对应的一个service,一个对象
简介:根据表生成mapper层三层部分代码:实体类,mapper接口,映射文件
创建工程:crm-mybatis-generator
添加插件:
- <!--myBatis逆向工程插件-->
- <plugin>
- <groupId>org.mybatis.generator</groupId>
- <artifactId>mybatis-generator-maven-plugin</artifactId>
- <version>1.3.2</version>
- <configuration>
- <verbose>true</verbose>
- <overwrite>true</overwrite>
- </configuration>
- </plugin>
需要配置:
数据库连接信息
代码保存的目录
表的信息
运行mybatis的逆向工程,根据指定的表
选择器.attr(“属性值名”);//用来获取哪些值不是true或者false的属性的值
选择器.prop("属性名");//用来获取值是true/false 的属性值
选择器.click(function(){})//给指定的元素添加事件
选择器.click();//给指定的元素上模拟发生一次点击事件
把控制层(controller)处理好的数据传到视图层(jsp),使用作用域传递;
四大作用域:
pageContext:同页面内传参数,用来在同一个页面不同标签之间传递数据
request:在同一个请求之间传输数据。(请求完成后,会消失(不能重定向))
session:同一个浏览器,不同请求之间传递数据(服务器停止前,都有效)
application:所有用户共享的数据,而且长久频繁使用的数据。
实现点击回车,确认登录功能:
- //给整个登录窗口添加键盘按下事件-------------实现点击回车,自动登录
- $(window).keydown(function (e){
- //判断是否按键为回车键,,是,则提交登录请求,否则不做响应
- if(e.keyCode===13){//回车的Ascall码为13
- $("#loginBtn").click()
- }
- })
- //如果需要记住密码,则往外写Cookie
- if("true".equals(isRemember)){//选择记住密码
- System.out.println("到了!!");
- //账号
- Cookie cookie1 = new Cookie("loginAct", user.getLoginAct());
- cookie1.setMaxAge(10*24*60*60);//设置声明周期,10天后自动删除
- response.addCookie(cookie1);
- //密码
- Cookie cookie2 = new Cookie("loginPwd", user.getLoginPwd());
- cookie2.setMaxAge(10*24*60*60);//设置声明周期,10天后自动删除
- response.addCookie(cookie2);
- }else{//选择不记住密码
- //把没有过期cookie删除,不能直接删除客户端的Cookie,通过覆盖,设置生命周期,来达到同样效果
- Cookie cookie1 = new Cookie("loginAct", "1");
- cookie1.setMaxAge(0);
- response.addCookie(cookie1);
- Cookie cookie2 = new Cookie("loginPwd", "1");
- cookie2.setMaxAge(0);
- response.addCookie(cookie2);
- }
通过判断和记录Cookie记录
实现思路:每次登录,判断是否需要记住密码,如果需要,则写Cookie。而且把用户的账号和密码保存在Cookie里面
下次登录,判断该用户有没有Cookie,没有,则不填,有,则填写Cookie值,即自动填写账号和密码,
页面获取Cookie的方法:
P38集
借助SpringMVC的拦截器HandlerInterceptor实现验证功能
前期映射路径命名规则有利于拦截器使用:
1--写拦截类
- public class LoginInterceptor implements HandlerInterceptor {
- //访问目标资源前,执行
- @Override
- public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
- //验证用户是否处于登录状态
- HttpSession session = httpServletRequest.getSession();//获取session对象
- User user = (User) session.getAttribute(Contants.SESSION_USER);
- if(user==null){//未登录,跳转到登录页面
- //重定向--需要加项目的名称(这里不是MVC框架范围,视图解析器不起作用,不帮忙加前后缀)
- httpServletResponse.sendRedirect(httpServletRequest.getContextPath());//手动重定向,url必须加项目的名称,httpServletRequest.getContextPath()=="/crm"
- return false;
- }else{//已登录,放行资源
- return true;
- }
-
- }
- @Override
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
-
- }
-
- @Override
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
-
- }
- }
2--配置拦截器
- <!-- 配置拦截器(拦截controller请求) -->
- <mvc:interceptors>
- <mvc:interceptor>
- <!-- "/settings/*":只表示settings下的一层子目录进行拦截, "/settings/**": 表示settings的所有多层子目录都进行拦截 -->
- <mvc:mapping path="/settings/**"/>
- <mvc:mapping path="/workbench/**"/>
- <!-- 配置排除拦截的请求(登录相关),排除的优先级高 -->
- <mvc:exclude-mapping path="/settings/qx/user/toLogin.do"/>
- <mvc:exclude-mapping path="/settings/qx/user/login.do"/>
- <!-- 不需要加这个,因为没有用到全局拦截“/**” <mvc:exclude-mapping path="/"/>-->
- <!-- 拦截器类 -->
- <bean class="online.sumu.crm.settings.web.interceptor.LoginInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
一个页面,可以由多个页面组成
技术1:<frameset>和<frame>(重标签,性能低)
<frameset>: 用来切割页面,只能按行或者列来切
<frame>: 显示页面,每一个<frame>标签就是一个独立的浏览器窗口
技术2:<div>和<iframe> (轻量标签,性能高)
<div> : 用来切割页面,即和之前用div一样就行
<iframe> :显示页面
1--创建(先实现创建模块,在做删改查)
模态窗口:模拟的窗口,不是真实弹出来的,本质上是div,通过设置z-index大小来实现;
初始时,z-index初始参数小于0,不显示;需要显示时,设置大于0,即可1显示
借助bootstrap框架来控制z-index的大小
方式1--通过框架的标签的属性date-toggle="modal“ :触发显示模态窗口,date-target=”模态窗口的id“ :指定显示某个模态窗口。
方式2--通过js函数控制
方式3-- 通过标签的属性data-dismiss=”“,通过点击添加了属性data-dismiss=”“的按钮,来关闭当前的模态窗口
模态窗口有利于获取要处理的数据
显示市场活动页面
p49
清空form表单里面所有输入框内容
//清空表单.get[0].reset(),, .get(0)为获取表单的全部DOM对象
$("#createActivityForm").get[0].reset()
满足这两个特定,说明有插件,现成的功能的直接cv就行
日历插件:bootstrap-datetimepicker
前端插使用步骤:
引入css和js等依赖资源,先引入被依赖的资源
$(function(){}) :为入口函数,只有页面其他资源加载完后,才执行
P63
在指定的标签中,显示jsp页面片段:
$("#tBody").html(html语句)//覆盖显示
$("#tBody").text(文本)//覆盖,只能添加文本
$("#tBody").append(html语句)//在尾部追加显示
$("#tBody").after(html语句)//追加显示
$("#tBody").before(html语句)//追加显示
分页插件:bs_pagination
使用步骤:
P74
(父元素:必须时固有元素,可以是直接父元素,也可以是间接父元素)
(事件类型:跟事件数据属性和事件函数意义对应)
(子元素:目标元素,跟父选择器构成一个父子选择器)
注意:使用使用jquery对象判定事件时,对于用在动态元素上,事件可能会失效,而固有元素则没问题
P85
js的截取字符串函数:
js求长度:
data:{
k1:v1,
k2:v2,
……
}
*优势:操作简单
*劣势:不能向后台提交一个参数名对应多个参数值的数据。否则会覆盖,只能提交字符串。
data:{
id:v1,
id:v2,
……}//后台只能获取最后一个id的值
data:k1=v1&k2:v2$……
*优势:可以向后台提交一个参数名对应多个参数值的数据
*劣势:需要拼接字符串,操作麻烦,只能提交字符串。
优势:不但能提交字符串数,还能提交二进制数据
劣势:操作更复杂
关键技术准备:
关于办公文档插件使用的基本思想:把办公文档的所有元素封装成普通的java类,程序员通过操作这些类达到操作办公文档的目的。
最基础的办公文档类:
使用Apache-poi生成excel文件:
1--添加依赖
- <!-- Excel文档依赖包 poi依赖-->
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi</artifactId>
- <version>3.15</version>
- </dependency>
2--使用封装类
web技术,涉及前后台技术
//所有的文件下载请求,只能发同步请求
- //所有的文件下载请求,只能发同步请求
- window.location.href = "workbench/activity/exportAllActivity.do"//同步请求
//浏览器收到响应数据后,默认情况下,直接在显示窗口打开响应信息
//即使打不开,也会调用其他应用程序打开,只有实在打不开,才回激活下载
//可以设置响应头信息,使浏览器默认直接下载。
- //设置响应头,是浏览器默认直接下载响应信息,且设置文件名为myStudent.xsl
- response.addHeader("Content-Disposition","attachment;filename=ActivityList.xls");
P108
技术准备:
文件上传:
前端上传文件三要素:
请求方式只能用:post
get:参数通过请求头提交到后台,参数放在url后边;只能向后台提交文本数据;对参数长度有限制;数据不安全;效率高;自动将得到的数据放在缓存(重复访问,用缓存,不需发新请求)。
post:参数通过请求体提交到后台,即能提交文件数据,又能够提交二进制数据(图片,视频等);理论上对参数长度没有限制;相对更安全;效率相对较低。
根据HTTP协议的规定,浏览器每次向后台提交参数,都会对参数进行统一编码;默认采用的的编码格式为urlencode,这种编码格式只能为文本数据进行编码;所以文件上传的表单编码格式只能用ultipart/form-data。
使用java解析excel文件: iText,apache-poi(这里工具对于excel文件操作都是双向的)
文件上传同步和异步都行
p125
要注意的时,用mvc框架接受页面传来的文件,需要去mvc核心配置文件配置文件上传解析器才能正常使用MultipartFile类
文件上传,如果需要用到文件里面的数据,则文件格式一定要跟用户约定好
技术上的问题解决不了,可以在业务上选择更好的方案
js获取文件名中的后缀子串(全部转成小写):
let fileType = activityFile.substr(activityFile.lastIndexOf(".")+1).toLocaleLowerCase()
jquery对象转DOM对象
&("#id").[0] 或者 &("#id").get(0)
用ajax上传文件:
- //发送请求----
- //FormData是ajax提供的接口,可以模拟键值对向后台提交参数
- //FormData不但能提交文本数据,还是提交二进制数据
- let formData = new FormData();
- //把文件数据放在formData中的键值对中
- formData.append("activityFile",File)//key要和后台获取文件的参数名对应
- $.ajax({
- url:"workbench/activity/importActivity.do",
- data:formData,//
- type:"post",//上传文件,必须为post
- processData:false,//设置ajax向后台提交参数前,是否把参数统一转为字符串,true--是,默认为true,当上传文件时,要设置为false
- contentType:false,//设置ajax向后台提交参数之前,是否把参数统一按urlencoded编码,默认为true,上传文件时,要设置为false,等同于form表单上的enctype=“mutipart/form-data”设置
- dataType:"json",
- success:function (data) {
- if (data.code=="1"){//导入成功
- alert("成功导入:"+data.retData+"条记录!")
- //关闭模态窗口
- $("#importActivityModal").modal("hide")
- //刷新页面
- queryActivityByConditionForPage(1, $("#page").bs_pagination('getOption', 'rowsPerPage'))
- }else{//导入成功
- //提示信息
- alert(data.message)
- //模态窗口不关闭
- $("#importActivityModal").modal("show")
- }
- }
- })
P 130
el表达式在js中使用:
- //获取表单数据
- let activityId = '${activity.id}'//el表达式在js使用,用''括起来,否则浏览器识别为变量
选择器.append(html):追加显示在指定标签的内部的后面
选择器.text(字符串):覆盖显示在标签内部
选择器.html(html):覆盖显示在标签内部
选择器.after(html):追加显示在指定标签的外部的后面(同级标签)
选择器.before(html):追加显示在指定标签的外部的前面(同级标签)
html页面是可拓展的标记语句,可以给指定的标签任意扩展属性,只要属性名名称不重复即可。且有扩展有两个主要目的;
优先考虑id属性,其次考虑name属性,只有id和name属性都不方便使用时,才考虑使用自定义属性。
- $("#remarkDivList").on('click',"a[name='deleteA']",function () {
- //收集参数( this是dom对象,要放在$()转为jquery对象 )---自定义属性
- let id = $(this).attr('remarkId')}
- //刷新页面(删除元素)
- $("#div_"+id).remove()//从页面中移除对应元素
P135--P158还没看
P158
统计图表:以更专业,更形象的形式展示系统中的数据。
销售漏斗图:展示商品销售数据,销售业绩
---------------------------------------- 2022/7/25转去学MyBatis Plus先--------------------------------
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。