day01
企业类型、项目类型、企业IT组成
项目研发流程、人员搭配
发展路线
常使用软件汇总
BUG、需求变更如何处理
需求变更如何处理:
里程碑计划表、开发计划表
原需求的变更:
1:首先判断需求变更的优先级和紧急度
如果优先级特别高。比较紧急,这样就需要优先安排,并且出具开发完成时间
如果优先级不高,不着急处理,则需要重新变更开发计划表(一般是将需求变更放到项目周期的最后一阶段处理)
需求变更肯定会处理。
2:判断当前需求变更是否已经影响了原有业务功能的系统流程
评估需求变更的周期,和风险。发邮件进行报备,并且申请技术支持。
新增需求的变更:
1:同上(1、2)
2:需要评估新增需求的工作量,将工作量进行邮件报备(新签订需求变更的合同)
BUG如何处理:
保持心态的淡定、淡定、淡定
1:开发环境
- 后台
开发工具中进行debug模式调试(断点调试),控制台日志
从下往上看,找第一个case by......
- 前端
SVN中down下来的,前端文件是前端人员提交的,后台只负责更新
1:先注释掉错误的代码
2:告诉前端修改,更新代码
- 服务器----数据库----开发数据库
- 网络-----数据库-----开发数据库
2:测试环境
- 后台
logs文件----需求下载日志文件(问题重现时间段内的日志),
根据时间段,日志文件,从下往上看,找第一个case by
ca....out
localhost-....log
localhost-manger....log
manger....log
- 前端
- 推前端
- 服务器
- 推运维
- 网络
- 推网管
3:线上环境(生产环境、正式环境)
- 后台
找运维去下载logs文件(邮件申请)
日志文件,需要根据时间段,从上往下看(找第一个接口协议请求或者第一个case by....)
报的错误代码:404、300、302、500、504
- 前端
- 服务器
- 网络
线上环境bug,如果提交或者分配解决人:
禅道跟踪管理系统(PHP-mysql---linux)---开源
测试人员需要将bug或者问题或者需求变更,提交到禅道系统中,并且选择分配人(解决人),点击保存---(系统会发邮件给解决人)
ID---解决中....
修改bug状态---已解决
解决bug个数的报表:
张三------10
李四-------4
开发人员,是息息相关的。
基本工资+年终奖(1个月工资)+(双薪)---12薪
季度奖金:
标准:工作量和付出(禅道)
KPI----工作指标
一般是一个月一评
自评:96分
上级领导评:95分
部门主管评:89分
最终分:89分
等级:
60以下:辞退
60-80:800
80-90:1000
90以上:1500
如何分析日志、定位问题
参考上面
如何部署补丁文件、如何上线
补丁:
修改代码之前需要注意:
在修改代码之前,必须进行SVN/git更新,修改代码,注意代码规范
//start likang 2018年1月17日11:46:47 ==TODO
//public String test1(){..sysou("123")...}
public String test1(){..sysou("3333")...}
//end
出补丁之前,再次进行代码更新
代码补丁:
war包:----表现层代码
jar包:----应用层代码
脚本补丁:
全部是.sql文件,每个sql语句最后都必须有一个;结束
每个.sql文件,最终结尾,都必须带有一个commit;
如果需要更新多个脚本补丁,则必须有一个所有脚本的总文件all.sql
文档补丁:
在文件中,必须在前面有一个文档修改的历史记录
补丁说明:
解决问题:
解决人:
解决时间:
联系方式:
部署说明:
1:首先停止》。。。。服务器
2:做好....备份
3:解压.....文件,到。。。。地方,
4:复制....文件,到。。。。。(覆盖、删除并复制)
5:更新,执行....sql文件
6:清除。。。。缓存
7:重启服务器
数据库、数据库服务器、框架、架构
数据库:
databasesName
数据库服务器:
mysql\oracle\sqlserver\DB2
框架:
spring\springMVC\hibernate\mybatis\springBoot
架构:
架构模式:
C/S
B/S
MVC模式----SOP框架架构----MVC---WS标准
SOPA---HTTP
微服务:
springBoot、cloud
SOP和微服务有什么区别?
分布式、集群、高并发、负载、缓存、云端
分布式:
不同的业务,不同的模块,不同的功能,分别部署到不同的服务器
集群:
相同的业务,相同的模块,相同的功能,分别部署到不同的服务器
高并发:
同一时刻,N个人,同时访问同一个功能
负载均衡:
一般取平均值,某一天,网站的访问人数5W,PV(点击量)
将这些点击量,进行均衡分配到不同的服务器进行处理
缓存:
一般缓存的是用户的请求数据,为了提高用户的体验,和访问速度,降低服务器承载的压力
云:
腾讯云、阿里云等
小明的故事
层次架构
技术架构
负载架构
如何做技术选型
二维码工具类
/**
*
* @author likang
* @date 2017-11-3 下午2:06:54
*/
public class QRCodeEncoderHandler {
public void encoderQRCode(String content, String imgPath) {
try {
Qrcode qrcodeHandler = new Qrcode();
// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
qrcodeHandler.setQrcodeErrorCorrect('M');
//编码模式:Numeric数字 Binary二进制 Kanji汉字 Alphanumeric英文字母
qrcodeHandler.setQrcodeEncodeMode('B');
qrcodeHandler.setQrcodeVersion(5);
byte[] contentBytes = content.getBytes("gb2312");
BufferedImage bufImg = new BufferedImage(600, 600,BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bufImg.createGraphics();
gs.setBackground(Color.WHITE);
gs.clearRect(0, 0, 600, 600);
// 设定图像颜色> BLACK
gs.setColor(Color.BLACK);
// 设置偏移量 不设置可能导致解析出错
int pixoff = 2;
// 输出内容> 二维码
if (contentBytes.length > 0 && contentBytes.length < 800) {
boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
for (int i = 0; i < codeOut.length; i++) {
for (int j = 0; j < codeOut.length; j++) {
if (codeOut[j][i]) {
gs.fillRect(j * 16 + pixoff, i * 16 + pixoff, 16, 16);
}
}
}
} else { }
gs.dispose();
bufImg.flush();
File imgFile = new File(imgPath);
// 生成二维码QRCode图片
ImageIO.write(bufImg, "png", imgFile);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
}
}
聊简历
个人信息:(无需照片)
姓 名: 性 别:
出生年月: 民 族:
学 历: 专 业:
籍 贯: 现 居:
手 机: 邮 箱:
专业技能:
1:精通java编程和设计模式,如:网络编程、多线程以及I/O流技术
2:具有良好的编码规范和设计思想,如工厂模式、代理模式、装饰模式、适配器模式等
3:熟练常见互联网框架技术,如:SSM、SSH等
4:熟练互联网常见前台框架,如:Bootstrap、easyUI、百度编辑器、Highcharts以及一些js插件等
5:熟悉常见的开源技术并且集成Spring和SpringMVC中,如:Quartz、Ehcache、ActiveMQ等
6:熟练掌握常见的关系型数据库mysql、oracle等以及非关系型数据库Redis、mongodb等
7:掌握常见的开发工具Myeclipse、Eclipse等IDE和版本控制器SVN、Git等,并熟练使用maven进行项目构建
8:熟练互联网常见的负载技术以及配置负载,如Nginx
9:掌握一些web应用服务器,如:Tomcat等,并能准确搭建集群环境
10:熟练掌握分布式项目服务,并熟练运用Dubbo进行分布式项目部署
11:具有良好的项目管理、需求把控等项目管理经验和风险控制经验
12:具有第三方登录、支付、高并发经验
13:在金融、房地产、支付等业务模块有很好的经验。
14:掌握常见的Linux操作命令
15:了解Spring Boot框架
项目经验(建议使用表格):
0-2:6K
2-3:6-10K
3-5:10-20K
5 +:20k+
项目名称: XXXXX
项目规模: (使用人数)(并发人数)
项目环境:linux、myeclipse、mysql57
应用技术:jdk1.7、Tomcat7、SpringMVC、mybatis、Spring、redis、......、Bootstrap(前端)、easyUI(后台管理系统)、开源技术、第三插件(百度编辑器、富文本插件、视频插件、jeecms)
项目描述:(3-5行即可)(业务。功能)
负责模块:(负责业务功能)
个人心得(不写):
工作经验:
eg:
2016.7-至今 百度 Java开发工程师
工作职责:
1:
2:
3:
教育经历:
2017.9-2018.11 北大 本科 计算机管理
个人评价:
工作期间,能够严格按照公司的制度规范自己,对工作认真负责,做到工作能够日结,对业务上能够很快的学习起来、入手快 ,能吃苦耐劳,用于承受压力,勇于创新。纪律性强,工作积极配合;意志坚强,具有较强的无私奉献精神。
工作中,我将发扬成绩,克服不足,以对工作、对事业高度负责的态度,脚踏实地,尽职尽责地做好各项工作,不辜负领导和同志们对我的期望。
HR常问问题:
1:能接受加班吗?可以接受加班,但是希望是有效率的加班
2:能接受出差吗?是短期出差还是长期的啊
3:地点能接受吗?
4:个人3-5年的职业规划?技术层次、管理层次
5:有带团队的能力吗?可以有、沟通能力
6:你觉得我们公司怎么样?氛围、团队组成
7:你期望在公司能获取什么样的进步或者帮助?技术层次、管理层次
问公司:
1:什么项目?项目组成员?
2:公司是否有架构师啊?
3:是否有定期的技术培训?
还有什么想问题的啊?
1:可以咨询待遇和福利问题?没有其他问题了
参考资料:
https://mp.weixin.qq.com/s/opv1e1OsTd1Nwf7nsHzg-w
项目-- 1 -- 【CRM客户管理系统】
调研
略
产品
略
需求
UI
略
开发
技术选型:
开发工具:myeclipse、linux、sqlyog
平台环境:jdk1.7、tomcat7、mysql5+、centos7
技术应用:SSM、bootstrap、富文本编辑器、websocket、js、jsp
框架搭建:
1:数据库设计
1:遵循数据库设计的数据类型规范,长度、注释等
2:一般建立索引的字段遵循两个规则
- 外键关联字段增加索引
- 增加查询或者搜索的字段增加索引
- 索引字段一张表,最多设置为16个索引
3:主键一般使用表名后缀+ID的方式设置,如:userId
4:表主键长度一般设置为20或者32,类型为Bigint
5:表主键可以选择自增模式,非空
6:表字段设计规范
- 日期字段--timestamp
- 金额字段---fload
- 富文本字段--text
- 状态字段----int 长度为1,并且注释上0123分别代表什么
- 字符串字段---varchar2
- 布尔值--boolean
2:框架搭建
- 在sqlyog客户端中,执行crm.sql文件
- 将CRM工程导入到本地工作空间
- 工程中引用tomcat的所有jar包
- 修改resource文件夹下jdbc的属性值,修改为自己的数据库连接信息
SQL:
hj_user 用户表 userid
hj_role 角色表 roleid
hj_dept 部门表 deptid
hj_menu 菜单表 menuid
hj_role_menu 角色-菜单关系表
-- 1:查询所有用户对应的角色和部门信息
select u.userid,u.username,u.roleid,r.rolename,u.deptid,d.deptname
from hj_user u
left join hj_role r on r.roleid = u.roleid
left join hj_dept d on d.deptid = u.deptid;
-- 2: 查询角色ID为37的对应的所有菜单信息 角色id,角色名称,菜单id,菜单名称
select r.roleid,r.rolename,rm.menuid,m.menuname
from hj_role r
left join hj_role_menu rm on rm.roleid = r.roleid
left join hj_menu m on m.menuid = rm.menuid
where r.roleid = 37;
-- 3:查询用户ID为2的用户,所拥有的菜单权限 /用户id,用户名称,角色ID,部门ID,菜单ID,菜单名称
select u.userid,u.username,u.roleid,u.deptid,rm.menuid,m.menuname
from hj_user u
left join hj_role_menu rm on rm.roleid = u.roleid
left join hj_menu m on m.menuid = rm.menuid
where u.userid = 2
框架说明:
web.xml:
spring\springMVC\后缀拦截.do\404\500
session有效期(分钟),如果没有配置,则去寻找tomcat中session配置
欢迎页、首页、日志信息
登录
跳转登录页面
1:完善web.xml信息,增加日志和监听
2:将拦截器中的注释放开
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>CRM_13</display-name>
<!-- spring配置信息 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springMVC配置信息 -->
<servlet>
<servlet-name>crm_13</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:context-dispatcher.xml</param-value>
</init-param>
<!-- 启用即加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 拦截后缀,后台使用do进行拦截,前端一般使用htm拦截或者jhtm拦截 -->
<servlet-mapping>
<servlet-name>crm_13</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 404、500 -->
<error-page>
<error-code>404</error-code><!-- 请求协议返回的错误代码 -->
<location>/404.do</location><!-- 接口地址 -->
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.do</location>
</error-page>
<!-- session有效期 -->
<session-config>
<session-timeout>120</session-timeout><!-- 默认为分钟 -->
</session-config>
<!-- 首页 -->
<welcome-file-list>
<welcome-file>/index.do</welcome-file><!-- 接口地址 -->
</welcome-file-list>
<!-- 编码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Log4j配置 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:/log4j.xml</param-value>
</context-param>
<!-- 加载log4j配置文件 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
实现步骤:
1:在src下的system.controller包下增加UserLoginController.java
2:将工程部署到tomcat中,并启动
3:直接输入访问工程名即可
UserLoginController.java
/**
* 登录功能
*
* @author likang
* @date 2018-1-18 下午2:06:14
*/
@Controller
public class UserLoginController {
/**
* 跳转登录页面
* @param model
* @return
*/
@RequestMapping(value = "/login.do", method = RequestMethod.GET)
public String toLogin(Model model) {
// 判断用户是否登录,如果登录,则跳转主页面,如果没有登录,则跳转登录页面
if (UserContext.getLoginUser() != null) {// 已经登录
return "redirect:/main.do";
}
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
/**
* 主页面的跳转
* @return
*/
@RequestMapping(value = "/main.do", method = RequestMethod.GET)
public String main() {
// 判断用户是否登录,如果登录,则跳转主页面,如果没有登录,则跳转登录页面
if (UserContext.getLoginUser() != null) {// 已经登录
return JumpViewConstants.SYSTEM_INDEX;
}
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
}
页面展示:
登录功能
开发步骤:
1:判断接收参数是否为空
2:判断用户名是否存在
3:判断密码是否匹配
4:如果都没问题,则需要设置session对象值
5:登录成功或者提示错误信息
6:解决禁用客户端cookie问题
主要代码:
UserLoginController.java:
/**
* 登录功能
* @author likang
* @date 2018-1-18 下午2:06:14
*/
@Controller
public class UserLoginController {
//auth---auth2
//出现这种关键词,则代表请求是安全的,数据是安全的
public static final String COOKIE_KEY = "auth_key";//登录时cookie的key
public static final String COOKIE_KEY_SEPARATE = "_#_";//登录时的cookie的分隔符
@Autowired
private IUserService userService;
/**
* 跳转登录页面
* @param model
* @return
*/
@RequestMapping(value = "/login.do", method = RequestMethod.GET)
public String toLogin(Model model) {
// 判断用户是否登录,如果登录,则跳转主页面,如果没有登录,则跳转登录页面
if (UserContext.getLoginUser() != null) {// 已经登录
return "redirect:/main.do";
}
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
/**
* 主页面的跳转
* @return
*/
@RequestMapping(value = "/main.do", method = RequestMethod.GET)
public String main() {
// 判断用户是否登录,如果登录,则跳转主页面,如果没有登录,则跳转登录页面
if (UserContext.getLoginUser() != null) {// 已经登录
//TODO 根据用户ID,查询用户所有的菜单信息
//Long userId = UserContext.getLoginUser().getUserid();
return JumpViewConstants.SYSTEM_INDEX;
}
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
/**
* 用户登录功能
* @param model
* @param email 邮箱名称
* @param password 密码
* @param sign
* @param request
* @return
*/
@RequestMapping(value = "/login.do",method = RequestMethod.POST)
public String login(Model model,String email,String password,String sign,HttpServletRequest request,HttpServletResponse response){
if (StringUtils.isNotBlank(email) && StringUtils.isNotBlank(password)) {
email = email+ContextUtil.getInitConfig("email_suffix");
//首先判断用户名是否存在
User user = userService.queryUserByEmail(email);
if (user != null) {//用户名存在
//需要匹配密码是否正确
boolean iseash = userService.isEashPasswordAndEmail(email, password);
if (iseash) {//true,则密码匹配成功
//设置session
UserContext.setLoginUser(user);
//解决用户关闭客户端cookie对象的设置
//需要在服务器中保存用户的cookie对象数据,每次请求或者获取数据,从服务器获取即可
Cookie cookie = new Cookie(COOKIE_KEY, URLEncoder.encode(email)+COOKIE_KEY_SEPARATE+MD5Tools.encode(password));
cookie.setMaxAge(0);//0:开启就一直存在
//-1:关闭即失效
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
request.getSession(true).setAttribute("loginName", user.getUsername());
request.getSession(true).setAttribute("ischange", user.getIschange());
//跳转主页面
return "redirect:/main.do";
}else{//密码不匹配
model.addAttribute("msg", ReturnConstants.PASSWORD_ERROR);
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
}else{
//如果不存在,则提示返回1
model.addAttribute("msg", ReturnConstants.USER_NOT_EXIST);
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
}
return ReturnConstants.PARAM_NULL;//接收参数为空
}
}
IUserService.java:
/**
* 用户管理接口
* @author likang
* @date 2018-1-18 下午3:30:43
*/
public interface IUserService {
/**
* 根据邮箱名查询用户是否存在
* @param email
* @return
*/
public User queryUserByEmail(String email);
/**
* 查询密码和邮箱是否匹配
* @param email 邮箱
* @param password 密码
* @return
*/
public boolean isEashPasswordAndEmail(String email,String password);
}
UserServiceImpl.java:
@Service
@Transactional(rollbackFor=Exception.class)
public class UserServiceImpl implements IUserService{
@Autowired
IDataAccess<User> userDao;
public User queryUserByEmail(String email) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("email", email);
//第一个参数代表sql语句的ID,第二个参数代表传入参数值,第三个代表分页
List<User> list = userDao.queryByStatment("queryUserByEmail", params, null);
if (list != null && list.size() > 0) {
return list.get(0);
}
return null;
}
public boolean isEashPasswordAndEmail(String email, String password) {
if (StringUtils.isNotBlank(email) || StringUtils.isNotBlank(password)) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("email", email);
params.put("password", MD5Tools.encode(password));
List<User> list = userDao.queryByStatment("isEashPasswordAndEmail", params, null);
if (list != null && list.size() > 0) {
return true;
}
}
return false;
}
}
mybatis-config.xml:
<mappers>
<mapper resource="commonsqlmappings/CommonMapper.xml" />
<mapper resource="mybatis/UserMapper.xml"/>
</mappers>
UserMapper.xml:
<mapper namespace="com.hjcrm.entity">
<!-- 查询用户是否存在 -->
<select id="queryUserByEmail" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.User">
select u.userid,u.username,u.roleid,u.deptid,u.email,u.ischange
from hj_user u
<if test="email != null and email !=''">
where u.email = #{email}
</if>
</select>
<!-- 查询邮箱和密码是否匹配 -->
<select id="isEashPasswordAndEmail" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.User">
select u.userid,u.username,u.roleid,u.deptid,u.email
from hj_user u where 1=1
<if test="email != null and email !=''">
and u.email = #{email}
</if>
<if test="password != null and password !=''">
and u.password=#{password}
</if>
</select>
</mapper>
页面展示:
主页左侧菜单功能
开发步骤:
1:在/main.do接口中,增加查询菜单的信息接口
2:将查询的数据,存放于model中,变量名为menus
3:在IUserService.java中增加根据角色ID,查询菜单权限的方法
4:实现接口方法,循环获取一级菜单和二级菜单并列表展示
5:在UserMapper.xml中,增加查询sql语句
6:代码如下
主要代码:
UserLoginController.java:
/**
* 主页面的跳转
* @return
*/
@RequestMapping(value = "/main.do", method = RequestMethod.GET)
public String main(Model model) {
// 判断用户是否登录,如果登录,则跳转主页面,如果没有登录,则跳转登录页面
if (UserContext.getLoginUser() != null) {// 已经登录
//TODO 根据角色ID,查询用户所有的菜单信息
Long roleid = UserContext.getLoginUser().getRoleid();
List<Menu> list = userService.queryAllMenuByRoleId(roleid);
model.addAttribute("menus", list);
return JumpViewConstants.SYSTEM_INDEX;
}
return JumpViewConstants.SYSTEM_LOGIN;// 登录页面
}
IUserService.java:
/**
* 根据角色ID,查询所有的角色菜单信息
* @param roleid
* @return
*/
public List<Menu> queryAllMenuByRoleId(Long roleid);
UserServiceImpl.java:
@Autowired
IDataAccess<Menu> menuDao;
public List<Menu> queryAllMenuByRoleId(Long roleid) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("roleid", roleid);
params.put("queryparent", "true");//是一个特殊标志,标志sql语句是查询一级菜单还是查询二级菜单,
//如果不为空,则代表只查询一级菜单,如果为空,则代表只查询二级菜单
//1:只查询一级菜单
List<Menu> list = menuDao.queryByStatment("queryAllMenuByRoleId", params, null);
//2:循环一级菜单,查询一级菜单所有的二级菜单
for (int i = 0; i < list.size(); i++) {
Long menuId = list.get(i).getMenuid();//一级菜单的ID,----将此ID,当做下一条sql的父ID
params.clear();
params.put("menuparaid", menuId);
params.put("roleid", roleid);
params.put("queryparent", null);
List<Menu> list1 = menuDao.queryByStatment("queryAllMenuByRoleId", params, null);
list.get(i).setChildren(list1);
}
return list;
}
UserMapper.xml:
<!-- 根据角色ID,查询角色所有菜单权限 -->
<select id="queryAllMenuByRoleId" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.Menu">
select r.roleid,r.rolename,rm.menuid,m.menuname
from hj_role r
left join hj_role_menu rm on rm.roleid = r.roleid
left join hj_menu m on m.menuid = rm.menuid
<if test="roleid != null and roleid != '' and queryparent !=null">
where r.roleid = #{roleid} and m.menuparaid is null
</if>
<if test="menuparaid != null and menuparaid != '' and queryparent ==null">
where m.menuparaid = #{menuparaid} and r.roleid = #{roleid}
</if>
</select>
页面展示
退出功能
开发步骤:
1:增加退出接口
2:清除浏览器和服务器cookie信息
3:重定向到main.do
主要代码:
UserLoginController.java:
/**
* 退出功能
* @param request
* @param response
* @return
*/
@RequestMapping(value="/logout.do",method=RequestMethod.GET)
public String logout(HttpServletRequest request,HttpServletResponse response){
UserContext.clearLoginUser();//清除session中的用户信息
//清除服务器cookie
Cookie cookieJSes = new Cookie("JSESSIONID",null);
cookieJSes.setMaxAge(0);
cookieJSes.setPath(request.getContextPath());
response.addCookie(cookieJSes);
//清除客户端浏览器cookie
Cookie cookie = new Cookie(COOKIE_KEY, null);
cookie.setMaxAge(0);//立即失效
cookie.setPath("/");
response.addCookie(cookie);
return "redirect:/main.do";
}
页面展示:
用户管理模块
跳转用户管理页面
开发步骤:
1:新建一个用户管理模块的controller类
2:从数据库hj_menu中或者点击菜单才看控制器浏览器404,都可以获取接口地址
3:在controller中增加跳转方法
主要代码:
UserController.java:
/**
* 跳转用户管理接口
* @return
*/
@RequestMapping(value = "/system/userMang.do",method = RequestMethod.GET)
public String main(){
if (UserContext.getLoginUser() != null) {
return JumpViewConstants.SYSTEM_USER_MANAGE;//用户管理页面
}
return JumpViewConstants.SYSTEM_LOGIN;//登录页面
}
查询所有用户信息列表(支持分页)
开发步骤:
1:通过浏览器获取查询信息的接口地址
2:在controller中增加查询的接口方法
3:在IUserService中,增加查询用户信息的接口方法,支持分页
4:实现该方法
5:在UserMapper.xml中增加查询的sql语句
注意:controller中查询方法为@responseBody,返回json数据,需要继承BaseController.java,使用其转换json的公用方法
主要代码:
UserController.java:
/**
* 用户管理模块控制器
* @author likang
* @date 2018-1-19 上午11:27:27
*/
@Controller
public class UserController extends BaseController{
@Autowired
private IUserService userService;
/**
* 跳转用户管理接口
* @return
*/
@RequestMapping(value = "/system/userMang.do",method = RequestMethod.GET)
public String main(){
if (UserContext.getLoginUser() != null) {
return JumpViewConstants.SYSTEM_USER_MANAGE;//用户管理页面
}
return JumpViewConstants.SYSTEM_LOGIN;//登录页面
}
/**
* 查询用户列表信息
* @param request
* @param currentPage 第几页
* @param pageSize 每页请求个数
* @return
*/
@RequestMapping(value = "/system/userlist.do",method = RequestMethod.GET)
public @ResponseBody String queryAllUsers(HttpServletRequest request,Integer currentPage,Integer pageSize){
List<User> list = userService.queryAllUsers(processPageBean(pageSize, currentPage));
return jsonToPage(list);
}
}
IUserService.java:
/**
* 查询所有用户信息,支持分页
* @param pageBean
* @return
*/
public List<User> queryAllUsers(PageBean pageBean);
UserServiceImpl.java:
public List<User> queryAllUsers(PageBean pageBean) {
List<User> list = userDao.queryByStatment("queryAllUsers", null, pageBean);
return list;
}
UserMapper.xml:
<!-- 查询所有用户信息 -->
<select id="queryAllUsers" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.User">
select u.userid,u.username,u.roleid,u.deptid,u.email,u.ischange
from hj_user u
</select>
增加用户信息
开发步骤:
1:获取增加、修改用户的接口地址(控制台、浏览器都可以获取)
2:增加查询所有部门信息的接口
3:增加根据部门ID,查询部门下的角色信息接口
4:根据接收参数是否有userid来判断是增加还是修改
5:增加、修改、删除,无需写sql语句
主要代码:
UserController.java:
/**
* 增加或者修改用户信息
* @param request
* @param user
* @return
*/
@RequestMapping(value = "/system/saveOrUpdate.do",method = RequestMethod.POST)
public @ResponseBody String addOrUpdateUser(HttpServletRequest request , User user){
if (user != null) {
userService.saveOrUpdate(user);
return ReturnConstants.SUCCESS;//处理成功
}
return ReturnConstants.PARAM_NULL;//接收参数为空
}
IUserService.java:
/**
* 增加或者修改用户信息
* @param user
*/
public void saveOrUpdate(User user);
UserServiceImpl.java:
public void saveOrUpdate(User user) {
if (user != null) {
if (user.getUserid() != null) {//修改
user.setUpdate_id(UserContext.getLoginUser().getUserid());
user.setUpdate_time(new Timestamp(System.currentTimeMillis()));
userDao.update(user);
}else{//增加
user.setCreate_id(UserContext.getLoginUser().getUserid());
user.setCreate_time(new Timestamp(System.currentTimeMillis()));
userDao.insert(user);
}
}
}
DeptController.java:
/**
* 部门模块信息控制器
* @author likang
* @date 2018-1-20 上午8:53:20
*/
@Controller
public class DeptController extends BaseController{
@Autowired
private IDeptService deptService;
/**
* 查询所有部门信息
* @param request
* @return
*/
@RequestMapping(value = "/dept/queryDept.do",method = RequestMethod.GET)
public @ResponseBody String queryAllDept(HttpServletRequest request){
List<Dept> list = deptService.queryAllDept();
return jsonToPage(list);
}
}
IDeptService.java:
/**
* 部门信息接口
* @author likang
* @date 2018-1-20 上午8:54:27
*/
public interface IDeptService {
/**
* 查询所有部门信息
* @return
*/
public List<Dept> queryAllDept();
}
DeptServiceImpl.java:
@Service
@Transactional(rollbackFor=Exception.class)
public class DeptServiceImpl implements IDeptService{
@Autowired
IDataAccess<Dept> deptDao;
public List<Dept> queryAllDept() {
List<Dept> list = deptDao.queryByStatment("queryAllDept", null, null);
return list;
}
}
DeptMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hjcrm.entity">
<!-- 查询所有部门信息 -->
<select id="queryAllDept" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.Dept">
select * from hj_dept
</select>
</mapper>
RoleController.java:
/**
* 角色管理模块控制器
* @author likang
* @date 2018-1-20 上午9:02:44
*/
@Controller
public class RoleController extends BaseController{
@Autowired
private IRoleService roleService;
/**
* 根据部门ID,查询角色对应信息
* @param request
* @param deptid 部门ID
* @return
*/
@RequestMapping(value = "/role/queryRoleByDeptid.do",method = RequestMethod.GET)
public @ResponseBody String queryRoleByDeptId(HttpServletRequest request,Long deptid){
List<Role> list = roleService.queryRoleByDeptId(deptid);
return jsonToPage(list);
}
}
IRoleService.java:
/**
* 角色管理接口
* @author likang
* @date 2018-1-20 上午9:06:04
*/
public interface IRoleService {
/**
* 根据部门id,查询对应的角色信息
* @param deptid
* @return
*/
public List<Role> queryRoleByDeptId(Long deptid);
}
RoleServiceImpl.java:
@Service
@Transactional(rollbackFor=Exception.class)
public class RoleServiceImpl implements IRoleService{
@Autowired
IDataAccess<Role> roleDao;
public List<Role> queryRoleByDeptId(Long deptid) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("deptid", deptid);
List<Role> list = roleDao.queryByStatment("queryRoleByDeptId", params, null);
return list;
}
}
RoleMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hjcrm.entity">
<!-- 根据部门ID,查询角色信息 -->
<select id="queryRoleByDeptId" parameterType="java.util.Map" resultType="com.hjcrm.system.entity.Role">
select * from hj_role r where r.deptid = #{deptid}
</select>
</mapper>
mybatis-config.xml:
<mapper resource="mybatis/DeptMapper.xml"/>
<mapper resource="mybatis/RoleMapper.xml"/>
删除用户信息(支持批量)
开发步骤:
1:获取删除用户信息的接口地址
2:在控制器层增加删除方法
3:推荐使用批量删除的api
主要代码:
UserController.java:
/**
* 删除用户信息,支持批量删除
* @param request
* @param ids 批量用户主键ID,(用逗号隔开)
* @return
*/
@RequestMapping(value = "/system/deleteUser.do",method = RequestMethod.POST)
public @ResponseBody String deleteUsers(HttpServletRequest request , String ids){
if (StringUtils.isNotBlank(ids)) {
userService.deleteUserByIds(ids);
return ReturnConstants.SUCCESS;
}
return ReturnConstants.PARAM_NULL;//接收参数为空
}
IUserService.java:
/**
* 删除用户信息,支持批量删除
* @param ids id用逗号隔开
*/
public void deleteUserByIds(String ids);
UserServiceImpl.java:
public void deleteUserByIds(String ids) {
if (StringUtils.isNotBlank(ids)) {
userDao.deleteByIds(User.class, ids);
// for (String id : ids.split(",")) {
// User user = new User();
// user.setUserid(Long.valueOf(id));
// userDao.delete(user);
// }
// userDao.deleteByStatment("deleteUserByIds", ids);
}
}
页面展示
定时任务-Quartz+spring集成
1:导包
2:增加定时任务的配置文件
参考模块信息
3:在spring的配置文件中,引用quartz的配置文件信息
<import resource="applicationContext-quartz.xml"/>
菜单管理模块
跳转、增加、查询功能
略
删除功能
角色管理模块
跳转、增加、查询、删除功能
略
权限分配功能
部门管理模块
参考工程文件
课程管理模块
参考工程文件
科目管理模块
参考工程文件
消息管理模块
跳转、增加、查询功能
略
发布、撤回功能
资源管理模块--运营部
资源管理模块-销售部
学员管理模块-销售部
学员管理模块-行政部
缓存
注解使用:
@Cacheable(value="baseCache",key="'queryAllDept'")
//存放缓存到缓存块中(baseCache),key值支持el表达式,字符,数字
//key值一般有三种方式,1:使用方法名当做key值 2:使用el表达式从参数属性中获取值#user.userid 3:使用字符串当做key
@CacheEvict(value="",key = "",beforeInvocation=false,allEntries = false)
// 清除缓存
//beforeInvocation为false,则代表是在执行代码之前进行清除,如果为true代表是在执行完代码之后进行删除
//allEntries=true,则代表清除所有的缓存块,如果allEntries=false,则只会清除key值对应的缓存数据
@CachePut() //更新缓存
步骤:
导入缓存包
1:增加eacache.xml属性文件,指明缓存区域块
2:增加和spring进行整合的配置文件
3:在spring的配置文件中,引用整合配置文件
<import resource="applicationContext-ehcache.xml"/>
eacache.xml:
参考工程文件
applicationContext-ehcache.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:oxm="http://www.springframework.org/schema/oxm"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 缓存 属性-->
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
<!-- 支持缓存注解 -->
<cache:annotation-driven cache-manager="cacheManager" />
<!-- 默认是cacheManager -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="cacheManagerFactory"/>
</bean>
</beans>
Linux如何搭建Java环境
Excel导入、导出
使用POI技术
导入:
1:需要将excel写入到服务器
2:从服务器中读取Excel
3:将读取到的内容,保存到数据库
导出:
1:将需要导出的数据,导出到服务器excel中
2:读取服务器中excel文件
3:将excel文件从服务器下载到本地
代码:
参考工程文件
使用websocket技术,实现消息的传输
使用tomcat7自带的websocket技术,实现消息的长连接模式传输
1:组装发送的消息对象
2:将消息对象放入到线程池中,避免高并发业务下,所引起的消息发送混乱或者丢失
3:将消息线程池放到线程池中,集中管理,并发送已经在连接中的线程
代码:
参考工程文件