目录
EncodingFilter:过滤器,我这个过滤器就是防止在传输过程中的时候产生乱码:
MVC是一种软件架构模式,把整个软件分为三层:Model,View,Controller
Model:模型---负责获取并数据,并且处理数据,返回给controller
entity:数据库的实体类
service:业务控制层,其余的话都交给service
dao:databaseObject数据模型层:只操作数据库
View:视图---看见的页面,渲染数据,渲染页面,负责展示而且允许用户编辑来自应用程序的Model对象,View对象用来构建用户界面,与用户交互。
Controller:控制器---servlet,接请求,给出响应,负责传递数据,监听各种事件,管理其他对象生命周期
耦合度(代码之间的关联关系)分层,把程序分层,改bug的时候,不用找的眼花缭乱,方便找
降低耦合,重用性,可维护性比较高
View层发起请求---Controller---Servlet---Dao---Servlet---Controller---View
总之,我们通过 MVC 设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。
MVC 并不适合小型甚至中型规模的项目,花费大量时间将 MVC 应用到规模并不是很大的应用程序,通常得不偿失,所以对于 MVC 设计模式的使用要根据具体的应用场景来决定。
接下来通过一个简单的项目结构,来展示一下:
controller包代表的是控制器,用来接请求,给响应
dao包代表数据模型层,只用来操作数据库
entiy包代表实体类,用来储存元素并提供get/set/构造器方法
filter包代表的是过滤器,用来筛选信息的
service包代表的是业务控制层,其余的“脏活累活都交给他干”
util包代表工具类
因为是结合实例写的,所以会有关于每个类中的一些做项目时产生的问题,就直接解决了
我们之前的做法是一个servlet就只处理一个请求
那么一个servlet能不能处理过个post请求?可以,利用反射:
- @WebServlet("*.do")
- public class VipController extends HttpServlet {
- //调用service
- private VipService vipService = new VipServiceImpl();
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //获取请求的路径
- String servletPath = req.getServletPath();
- System.out.println(servletPath);
- //截取地址:截取成eg:vip
- String method =servletPath.substring(1);
- method = method.substring(method.lastIndexOf("/")+1,method.length()-3);
- //利用反射执行vip方法
- // 拿到当前类对象
- try {
- Method method1 = getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
- method1.invoke(this,req,resp);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- private void vip(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String username = req.getParameter("username");
- String password = req.getParameter("password");
- String gender = req.getParameter("gender");
- String name = req.getParameter("name");
- System.out.println(username+password+gender+name);
- Vip vip = new Vip(username,password,gender,name);
- int i = vipService.register(vip);
- if(i>0){
- resp.sendRedirect(req.getContextPath()+"/success.html");
- }else{
- resp.sendRedirect(req.getContextPath()+"/fail.html");
- }
- }
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
- public interface VipDao {
- int save(Vip vip) throws Exception;
- }
- public class VipDaoImpl extends DAOImpl
implements VipDao { - @Override
- public int save(Vip vip) throws Exception {
- String sql ="insert into mvc(username,password,gender,name,salt) values (?,?,?,?,?)";
- System.out.println("sql");
- return update(sql,vip.getUsername(),vip.getPassword(),vip.getGender(),vip.getName(),vip.getSalt());
- }
- }
先整个序列化,然后创建对应数据库里所有的属性。并赋予get/set方法
- package mvc.entiy;
-
- import java.io.Serializable;
-
- public class Vip implements Serializable {
- private static final long serialVersionUID=-12389731289739127L;
- private Integer id;
- private String username;
- private String password;
- private String gender;
- private String profile;
- private String name;
- private String salt;
-
- public String getSalt() {
- return salt;
- }
-
- public void setSalt(String salt) {
- this.salt = salt;
- }
- public Vip(){
-
- }
-
- public Vip(String username, String password, String gender, String name) {
- this.username = username;
- this.password = password;
- this.gender = gender;
- this.name = name;
- }
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public String getGender() {
- return gender;
- }
-
- public void setGender(String gender) {
- this.gender = gender;
- }
-
- public String getProfile() {
- return profile;
- }
-
- public void setProfile(String profile) {
- this.profile = profile;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Vip{" +
- "id=" + id +
- ", username='" + username + '\'' +
- ", password='" + password + '\'' +
- ", gender='" + gender + '\'' +
- ", profile='" + profile + '\'' +
- ", name='" + name + '\'' +
- '}';
- }
- }
- @WebFilter("/*")
- public class EncodingFilter implements Filter {
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- System.out.println("filter");
- servletRequest.setCharacterEncoding("utf-8");
- response.setCharacterEncoding("utf-8");
-
- // 放行
- filterChain.doFilter(servletRequest,servletResponse);
- }
- }
- public interface VipService {
- //注册的方法
- int register(Vip vip);
- }
这里面有个不算拓展的拓展:进行密码的加密处理,毕竟密码不可能直接就存到数据库里,万一数据库被黑客或者某些人攻击或者窃取,这些密码不久流失了吗
进行密码加密:
调用在工具类里写的getSalt方法,获取盐,加到密码上
利用MD5加密处理:MD5Util.stringToMD5(密码);
再把密码存到Vip的set方法里
密码在加盐加密过后登录的时候怎么办?
登录的时候,还得按照加盐加密的形式来对比,还得需要拿着123456密码和之前加密的时候的盐再按照规则加密过后再比对
问题:我们能找到上次加密的时候用的那个盐吗? 我们需要把加密时候用的盐记录下来,登录的时候还需要使用!!!
唯一的办法,就是把盐存在数据库里
- public class VipServiceImpl implements VipService {
- private VipDao dao = new VipDaoImpl();
- @Override
- public int register(Vip vip) {
- //注册的业务执行的就是保存的操作
- try {
- //密码的加密处理
- //生成盐
- String salt = MD5Util.getSalt();
- String newPassword = MD5Util.stringToMD5(vip.getPassword() + salt);
- vip.setPassword(newPassword);
- // vip.setPassword(MD5Util.stringToMD5(vip.getPassword() + MD5Util.getSalt()));
- System.out.println("service");
- vip.setSalt(salt);
- return dao.save(vip);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
- public interface DAO<T> {
-
- /**
- * 更新
- * @return
- */
- int update(String sql,Object ... args) throws Exception;
-
- /**
- * 通用的查询所有
- */
- List<T> getForList(String sql,Object... args) throws Exception;
-
- /**
- * 通用的查询单个
- */
- T get(String sql,Object...args) throws Exception;
-
- /**
- * 查询某一个列的值,统计
- */
- <E> E getForValue(String sql,Object ... args) throws SQLException;
-
- }
-
- public class DAOImpl<T> implements DAO<T> {
-
- private QueryRunner runner = null;
- private Class<T> type;
-
- /**
- * 这个构造器中在做的事:
- * 为了获取Class
type = Teacher.class - */
- public DAOImpl() {
- runner = new QueryRunner(JDBCUtil.getDataSource());
- // 获得当前类的带有泛型类型的父类(运行期this其实是DAOImpl的某个子类)
- ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
- type = (Class<T>) ptClass.getActualTypeArguments()[0];
- }
-
- /**
- * 通用的增删改
- * @param sql
- * @param args
- * @return
- * @throws Exception
- */
- @Override
- public int update(String sql, Object... args) throws Exception {
- System.out.println("成功");
- return runner.update(sql,args);
- }
-
- /**
- * 根据sql语句查询多条记录
- * @param sql
- * @param args
- * @return
- * @throws Exception
- */
- @Override
- public List<T> getForList(String sql, Object... args) throws Exception {
- return runner.query(sql,new BeanListHandler<>(type),args);
- }
-
- /**
- * 根据sql语句查询一条记录
- * @param sql
- * @param args
- * @return
- * @throws Exception
- */
- @Override
- public T get(String sql, Object... args) throws Exception {
- return runner.query(sql,new BeanHandler<>(type),args);
- }
-
- /**
- * 根据sql语句查询某一列的值
- * @param sql
- * @param args
- * @return
- * @param
- * @throws SQLException
- */
- @Override
- public <E> E getForValue(String sql, Object... args) throws SQLException {
-
- return (E) runner.query(sql,new ScalarHandler<>(),args);
- }
- }
用德鲁伊来连接数据库
- public class JDBCUtil {
-
- private static final DataSource DATA_SOURCE;
-
- static {
- Properties properties = new Properties();
- try {
- properties.load(JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
- DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public static DataSource getDataSource() {
- return DATA_SOURCE;
- }
-
- }
加密方法
- public class MD5Util {
- /*
- 这个方法的参数是原始密码,在controller通过request.getParameter("")接到的写在密码框中的密码
- 返回值是经过加密处理过后的密码
- 加盐 salt
- MD5+盐 加密
- */
- public static String getSalt(){
- // 从我定义的一组数据中拿出几个字母或者数字或者符号当作盐
- String words="qwertyuioplkjhgfdsazxcvbnm,./;'[]~!@#$%^&*()_+-=0123456789";
- StringBuilder strb = new StringBuilder();
- for (int i = 0; i <8 ; i++) {
- //从我定义的数据中取x个字符当做盐,这里取了八个
- // 随机取,生成一个0到字符串的长度的随机数
- strb.append(words.charAt((int)Math.floor(Math.random()*words.length()-1)));
- }
- return strb.toString();
- }
- public static String stringToMD5(String str){
- return DigestUtils.md5Hex(str.getBytes());
- }
- }