注:本人是学习的新手,很多不懂得和很多要学习的,希望大家多多给建议,多多交流。
一.资料清单:
1.mysql必知会
链接: https://pan.baidu.com/s/1UhwS-rHBio1ksk5fgUr1Ig 提取码: t2z4
2.JSP&Servlet学习笔记(第二版)
链接: https://pan.baidu.com/s/1BJx2x00vTGegYXN0KunRlg 提取码: pwte
3.powerdesigner安装包及破解文件
链接: https://pan.baidu.com/s/1-LzNG-fdSv07NOXKxiY2Aw 提取码: br7q
4.PowerDesigner之PDM(物理概念模型)软件操作
链接: https://pan.baidu.com/s/1Ni3RxXGMgkkHm_myOAV4og 提取码: ts3u
5.使用PowerDesigner画ER图详细教程
链接: https://pan.baidu.com/s/1mpv6gZ9-bIp-OXjpqLfQpg 提取码: y9np
6.个人博客静态html资源
链接: https://pan.baidu.com/s/1jHGnCkTGf0AbJVgdniFsNQ 提取码: uiju
7.intellij_ideal创建maven-Springmvc简单教程
链接: https://pan.baidu.com/s/1e00nd1_PE3f5AIo6Wcc_QA 提取码: d44v
8.ajax课程
链接: https://pan.baidu.com/s/1c1INKFHgrdxnqufzEAMD5g 提取码: fjna
9.http协议
链接: https://pan.baidu.com/s/11q8AVZ3VqHDvFSp-XdDE-g 提取码: e5gm
10.tomcat结构及处理请求过程。
链接: https://pan.baidu.com/s/1a2YcWY320QGzangOdtSPig 提取码: vu7v
二.项目开发前概述
本来是我做C的终端开发的,工作内容比较简单,但是重复劳动力很多,且不能学习新的东西。后来公司出了Android智能终端,我就着手学习Android,一直到可以独立开发项目。随着时间慢慢过去,回首突然发现,这些前端的东西变化的太快了,而且随着微信小程序的普及和广泛使用,Andorid对于我的职业生涯规划来说也不是很好。我决定花时间来学习Java Web后端的开发。我知道这个周期会很长,但是只要能有进步的空间,我觉得这是很好的事情。
言归正传,我的学习过程其实也比较简单,百度查了下Web开发的路线,我找到了两个比较好的博客,文章都是坐着转载的找不到原地址了。
——Java和web方向的学习路线
https://blog.csdn.net/yl1712725180/article/details/79329865#
——java学习路线图(2018年最新版)
https://blog.csdn.net/chenshiyang0806/article/details/79879269
接下来就是学习了,通过数据库(mysql必知会)和servlet(Servlet学习笔记)的学习后,大致有了一个基本的概念,准备着手开发一个博客项目,来巩固自己的知识了。
直接上手写代码吧,很多东西不清晰,也不知道从何下手。百度了下,powerdesigner是一个很好的开发人员的模型工具,接下来就着手powerdesigner的学习,学习过程大概花了两三天左右的时间,上述资料清单里面有相关资料。
接着就使用powerdesigner来画物理模型,借鉴了CSDN~猫扑以及其他论坛网站的前端,完善了我的一些基本的模型。随着项目的推进,该项目的物理模型肯定会有变化的。目前的概念模型如下图。
学习powersigner了解了几种模型和它们之间的关系,以及一些基本的软件操作。当然目前只能说懂一点皮毛,不过这个的确是方便,开发项目的时候很有必要,建议大家学习下。学习的时候因为没有具体书籍,所以只能从网上找资料,我自己个人总结了一些基本的操作上上面的链接里。
学习powersigner之后,开始从网上找到了一个前端页面的例子(找这个资源花了半天时间,因为我觉得没有好的页面做出来的后端再好也没有啥用,所以美观的前端很重要,为了找到漂亮的,我愿意花半天时间专门找这个资源),在此感谢大神的分享(我只有一些前端的基础),在此例子的基础上开发,只能说有点难,前端的东西不是我能处理的。下图是这个静态资源的首页展示。
学习intellij ideal如何开发web项目(我之前学习的时候使用myeclipse,现在使用intellij ideal。intellij ideal开发起来太方便了,尤其是其优雅地代码提示,本人推荐使用intellij ideal。突然接触intellij ideal的时候也是一脸懵,不知道如何下手。狠心花了半天时间从网上找资料,琢磨了intellij ideal如何使用。现在终于能算是入门了。能好好开发我的项目了。
二.目前开过程
对前段做些简单处理吧,网上的资源虽然漂亮,但是重复代码太多,尤其一些head标签里面的内容,导航,底部等都是重复的,现在需要把这些内容抽取出来,我使用的是tag file来处理。另外我也针对我的博客功能修改和删除了一些东西。还有就是页面里面的内容都是英文的,算了,这个我用到哪里改到哪里吧,目前处理后大概是这个样子的。
导航栏,里面的数据项肯定要放数据库里面的,这样方便控制。下图是我的物理模型图具体内容。more字段是true的,就当把内容放入导航栏更多子菜单。对了,我对博客内容的一级分类叫区(学习猫扑)。
获取导航栏的数据内容并展示在页面。此时发现了一个问题,就是每次加载页面的话都从数据库获取数据,这样会不会效率太慢,而且导航栏一般也不会随意改动,所以我增加了一个ServletContextListener,在应用启动的时候把获取到的数据塞入ServletContext的属性中。如果以后改动了导航栏数据,就修改下属性即可。这样每次直接从内存中获取他并展示在页面。
关于数据库操作DaoImpl类,我直接使用的jdbc没有使用任何框架,也是为了巩固jdbc的学习。在这里有个问题想请教下。我现在是定义了所有DaoImpl的基类BaseDaoImpl,里面是一些常用变量我给声明了程序变量,还有关闭操作我给提取出来了。
使用数据源来获取数据库连接。数据库的连接获取我也抽取出来了,我现在的思路是把Connection弄成static对象,这样保证所有的DaoImpl类使用的都是一个Connection资源,并且在获取Connection之前先判断它是否为空或者是否为关闭状态,如果是也通过数据源获得Connection,如果不是则直接返回当前Connection。请大神看到了帮忙指正,这个问题仍然困扰着我。下面是我的基类代码。
package blog.dao.impl;
import blog.app.Constant;
import org.apache.log4j.Logger;
import javax.servlet.ServletContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* DAO实现类基类,获取连接,异常处理在这执行
*/
public class BaseDaoImpl {
ServletContext context;
//所有实例共享一个连接
static Connection connection;
PreparedStatement stmt;
ResultSet rs;
SQLException ex;
public BaseDaoImpl(ServletContext context){
this.context = context;
}
//获取Connection,如果连接已经关闭,则需要重新获得连接
Connection getConn() throws SQLException {
ex = null;
if(connection == null || connection.isClosed()) {
Logger.getLogger(BaseDaoImpl.class).info("数据库连接中...");
DataSource dataSource = (DataSource) context.getAttribute(Constant.dataSource);
connection = dataSource.getConnection();
}
return connection;
}
/**
* 关闭资源
* @param isConnClose-是否关闭数据库连接
*/
void close(boolean isConnClose){
if(rs != null){
try {
rs.close();
rs = null;
} catch (SQLException e) {
if(ex == null) {
ex = e;
}
}
}
if(stmt != null){
try {
stmt.close();
stmt = null;
} catch (SQLException e) {
if(ex == null) {
ex = e;
}
}
}
if(isConnClose && connection != null){
try {
connection.close();
connection = null;
} catch (SQLException e) {
if(ex == null) {
ex = e;
}
}
}
if(ex != null) {
Logger.getLogger(BaseDaoImpl.class).error(ex);
throw new RuntimeException(ex);
}
}
void rollback(){
try {
connection.rollback();
} catch (SQLException e) {
if(ex == null){
ex = e;
}
}
}
void commit(){
try {
connection.commit();
} catch (SQLException e) {
if(ex == null){
ex = e;
}
}
}
}
下面是一个用户角色操作类源码
package blog.dao.impl;
import blog.dao.RoleDao;
import blog.model.Role;
import javax.servlet.ServletContext;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class RoleDaoImpl extends BaseDaoImpl implements RoleDao {
public RoleDaoImpl(ServletContext context) {
super(context);
}
@Override
public Role getDefRole() {
Role role = null;
try {
connection = getConn();
stmt = connection.prepareStatement("SELECT id,name FROM role WHERE def = ?");
stmt.setBoolean(1,true);
rs = stmt.executeQuery();
if (rs.next()){
role = new Role();
role.setId(rs.getString("id"));
role.setName(rs.getString("name"));
}
} catch (SQLException e){
ex = e;
} finally {
close(false);
}
return role;
}
@Override
public void add(Role role) {
try {
connection = getConn();
stmt = connection.prepareStatement("INSERT INTO role (id,name,def) VALUES (?,?,?)");
stmt.setString(1,role.getId());
stmt.setString(2,role.getName());
stmt.setBoolean(3,role.isDef());
stmt.executeUpdate();
} catch (SQLException e) {
ex = e;
} finally {
close(false);
}
}
@Override
public void delete(Role role) {
try {
connection = getConn();
stmt = connection.prepareStatement("DELETE FROM role WHERE id = ?");
stmt.setString(1,role.getId());
stmt.executeUpdate();
} catch (SQLException e) {
ex = e;
} finally {
close(false);
}
}
@Override
public void update(Role role) {
try {
connection = getConn();
stmt = connection.prepareStatement("UPDATE role SET name=?, def=? WHERE id = ?");
stmt.setString(1,role.getName());
stmt.setBoolean(2,role.isDef());
stmt.setString(3,role.getId());
stmt.executeUpdate();
} catch (SQLException e) {
ex = e;
} finally {
close(false);
}
}
@Override
public List<Role> getAll() {
List<Role> roles = null;
try {
connection = getConn();
stmt = connection.prepareStatement("SELECT id,NAME,def FROM role");
rs = stmt.executeQuery();
roles = new ArrayList<>();
while (rs.next()) {
Role role = new Role();
role.setId(rs.getString("id"));
role.setName(rs.getString("name"));
role.setDef(rs.getBoolean("def"));
roles.add(role);
}
} catch (SQLException e) {
ex = e;
} finally {
close(false);
}
return roles;
}
}
用户注册开发,先是改了前端的内容,唉一言难尽,搞了好久。基础的操作有了,通过网页能实现数据插入了。然后是完善的过程,这个过程有点复杂。第一个就是使用js来判断输入元素内容是否合适正确了,这个还好。然后ajax来判断用户名是否存在,邮箱是否被注册的功能了。ajax之前没有接触过啊,算了,花了一天的时间来学习,了解它是什么,基础操作,然后就是ajax的jquery的操作了。我是在菜鸟教程里面学习ajax的基础的。这个网上资料很多,能用就行了。我把学习的也给写成了word文档了,里面不包括jquery的ajax操作。等这些都没有问题后,再用js对密码进行MD5加密,传给后端。
然后是过滤器了,首先是字符编码过滤器(Html标签转义和敏感词过滤都在这里处理)。唉,说到这个,踩了一个深坑,我学习Servlet的时候url-pattern指定的都是/*,在这个项目我也是用的这个。然后继续编写其他过滤器和其他功能。等项目跑起来的时候,发现页面没有样式了。排查花了有半天时间(一直琢磨到半夜3点,还是第二天发现问题的),各种百度,各种尝试,最后甚至还重新建了项目来跑,都没有解决。唉…,跟踪log发现可能是我这个过滤器的原因,因为/*把加载js和css都进行过滤了。后来把url-pattern改成*.do和*.jsp就好了。
敏感词过滤,首先也是在应用启动的时候,把敏感词放在内存,然后再处理的时候,直接从内存里面去取敏感词。接着就是如何优化敏感词的查找和替换时间了,这里再网上找了一会会资料。目前就先采用这个方案,速度还可以的。原文博客的连接找不到了,我就分享下现在的代码吧。
package blog.util;
import java.util.*;
/**
* 敏感词过滤实现工具类
*/
public class DirtyWordUtil {
private static StringBuilder replaceAll;//初始化
private static String replaceStr = "*";//敏感词替代字符串
private static int replaceSize = 500;
static {
replaceAll = new StringBuilder(replaceSize);
for(int x=0;x < replaceSize;x++)
{
replaceAll.append(replaceStr);
}
}
//过滤敏感词
public static String filterDirty(String value, List<String> dirties)
{
HashSet<String> sensitiveWordSet = new HashSet<String>();
List<String> sensitiveWordList= new ArrayList<>();
StringBuilder buffer = new StringBuilder(value);
HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>(dirties.size());
String temp;
for(int x = 0; x < dirties.size();x++)
{
temp = dirties.get(x);
int findIndexSize = 0;
for(int start = -1;(start=buffer.indexOf(temp,findIndexSize)) > -1;)
{
//System.out.println("###replace="+temp);
findIndexSize = start+temp.length();//从已找到的后面开始找
Integer mapStart = hash.get(start);//起始位置
if(mapStart == null || (mapStart != null && findIndexSize > mapStart))//满足1个,即可更新map
{
hash.put(start, findIndexSize);
//System.out.println("###敏感词:"+buffer.substring(start, findIndexSize));
}
}
}
Collection<Integer> values = hash.keySet();
for(Integer startIndex : values)
{
Integer endIndex = hash.get(startIndex);
//获取敏感词,并加入列表,用来统计数量
String sensitive = buffer.substring(startIndex, endIndex);
//System.out.println("###敏感词:"+sensitive);
if (!sensitive.contains("*")) {//添加敏感词到集合
sensitiveWordSet.add(sensitive);
sensitiveWordList.add(sensitive);
}
buffer.replace(startIndex, endIndex, replaceAll.substring(0,endIndex-startIndex));
}
hash.clear();
return buffer.toString();
}
}
发现加载页面有些慢,因为图片资源比较多嘛,就增加了压缩响应数据过滤器。编码是比较简单的,网上参考资料即可。在测试时候发现数据有的压缩后变小了,有的压缩后反而大了,百度了下知道了原因,所以在前人的基础上加了个判断。比较部分如下图。
暂时别的过滤器还没有处理,这个等以后用到了在增加。
再然后是登录页面忘记密码这个功能了。因为是学习,而且又不是为了赚钱,就暂且用邮箱找回密码功能吧。
这个没有碰到什么大坑,我使用的是自己的qq邮箱作为服务器邮箱了,百度了下怎么玩的,然后就操作了。邮件内容是什么格式是使用的一个简单的html模板来进行配置。 另外忘记密码的流程是,输入用户名和邮箱,先用ajax判断他们是否存在,不存在就不允许提交了。然后在后台判断用户名和邮箱是否匹配。匹配则先生成新的密码,更新数据库,发送邮件到用户邮箱。
完。后面每天做了什么都会在记录在微博。