基于SSM框架的Web网站项目

我将手把手教大家完成一个基于SSM框架的web项目,实现注册、登录功能

注意:该项目需要的基础知识为Java/H5/CSS3/JS/JSON/AJAX/Servlet/JSP/SSM

一、 搭建开发环境(准备阶段)

  1. 安装JDK(JDK安装过程自行百度),目前我用的JDK版本是1.8
  2. 安装Eclipse(用MyEclipse也是可以的,或者IDEA),只要能装Tomcat插件即可
  3. 安装Tomcat 8.5,下载地址,顺便啰嗦一句,7.0以上版本就已经不需要配置环境变量了,当然你也可以为tomcat配置环境变量。
  4. 安装mysql数据库(我的数据库版本是5.5)

二、需求分析

这里我们的需求分析比较简单,我们想要做一个网站的注册登录功能,这时候我们就会去想数据库需要哪些表呢?表里需要哪些字段呢?这里我们设计的表略简单,目的就是为了方便新手入门理解。注册登录一个表足以,我们创建一个名为web的数据库,然后新建一个用户user表,表里面的字段和内容如下:

usernamepassword
xxxf123456
xxxxf123456
方大大123456
测试员123456

这里,我也给出创建数据库和表的SQL语句:

CREATE DATABASE web;
USE web;
CREATE TABLE USER(
username VARCHAR(20) NOT NULL PRIMARY KEY COMMENT '账号',
PASSWORD VARCHAR(20) NOT NULL COMMENT '密码'
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO USER(username,PASSWORD) VALUES ('xxxf','123456');
INSERT INTO USER(username,PASSWORD) VALUES ('xxxxf','123456');
INSERT INTO USER(username,PASSWORD) VALUES ('方大大','123456');
INSERT INTO USER(username,PASSWORD) VALUES ('测试员','123456');

这里讲一下我们的业务逻辑,注册时会检查数据库有无此账号名,若有注册失败,若无则注册成功;登录时,检查数据库账号密码是否正确,账号或密码错误都会登录失败,并且前端会给返回提示。需求分析就这么多,还是蛮easy吧!

三、创建Web项目

  1. 打开Eclipse,选择File ->New->Dynamic Web Project ,新建名为PersonalWebSite的项目,一直选择next,最后把web.xml勾选上。
    这里写图片描述
    这里写图片描述
  2. 包结构
    这里写图片描述
    这里写图片描述
    这里简单解释一下src下每个包的作用:
    (1) POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。在POJO层我们创建的类,属性用private修饰,目的是为了封装属性,然后用getter&setter方法去获得或修改属性值。

    (2) DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。dao我们放了很多方法接口,在mapper层使用xml配置实现SQL语句的填充,这是使用mybatis的一贯做法。

    (3)Service层(biz):业务层 控制业务

    Service层主要负责业务模块的逻辑应用设计。和DAO层一样都是先设计接口,再创建要实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在service层调用接口进行业务逻辑应用的处理。
    封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

    (4)ServiceImpl:业务层的实现层
    service层只写了接口方法,并没有去真正去实现方法,在impl层我们会把具体实现方法写出来

    (5)Controller层: 控制层 控制业务逻辑

    Controller层负责具体的业务模块流程的控制,controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也需要在配置文件中进行。

    (6)config层:配置层
    一般来说,配置层在xml中实现也可,这里我用了java代码来实现SSM初始化配置,有三个类需要我们去关注,WebAPPInitialzer.java(配置类),RootConfig.java(Spring IoC上下文配置)、WebConfig.java(配置DispatchServlet上下文)

    (7)mybatis层:使用xml实现mybatis配置

四、SSM框架环境搭建

这里我使用的是全注解方式完成项目

首先我们需要做的是,把项目所需的jar包导入到你项目的WebContent/WEB-INF/lib或者是WebRoot/WEB-INF/lib下,这里我们的所依赖的JAR包有很多个,所以为了方便大家找到所需要的资源我将项目放到了github上,你只要访问我的Git仓库(戳这里),在WebContent/WEB-INF/lib下复制所有的jar包到你本地代码同样的目录下,再buildpath一下就可以使用啦!顺便提一下,这里面有很多jar包该项目并没有用到,为什么不删除呢?答案是:我比较懒,不想花时间去挑选JAR包。如果你用maven去构建项目,只需要在pom.xml把所需要的jar包信息配置上也可以达到相同的效果。

1.通过继承AbstractAnnotationConfigDispatcherServletInitializer(这个类名字巨长,反正我是记不住)去配置其他内容,因此首先来配置WebAPPInitialzer,如代码所示:

package com.xxxxf.config;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 *WebAPPInitialzer.java配置类
 */

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // Spring IoC环境配置
    @Override
    protected Class<?>[] getRootConfigClasses() {
        // 配置Spring IoC资源
        return new Class<?>[] { RootConfig.class };
    }

    // DispatcherServlet环境配置
    @Override
    protected Class<?>[] getServletConfigClasses() {
        // 加载Java配置类
        return new Class<?>[] { WebConfig.class };
    }

    // DispatchServlet拦截请求配置
    @Override
    protected String[] getServletMappings() {
        return new String[] { "*.do" };//拦截所有以.do结尾的请求
    }

    /**
     * @param dynamic
     *            Servlet上传文件配置.
     */
    @Override
    protected void customizeRegistration(Dynamic dynamic) {
        // 配置上传文件路径
        String filepath = "e:/mvc/uploads";
        // 5MB
        Long singleMax = (long) (5 * Math.pow(2, 20));
        // 10MB
        Long totalMax = (long) (10 * Math.pow(2, 20));
        // 设置上传文件配置
        dynamic.setMultipartConfig(new MultipartConfigElement(filepath, singleMax, totalMax, 0));
    }

}

2.上面代码重写的三个方法就可以配置Web工程中的Spring IoC资源和DispatchServlet的配置内容,然后是配置Spring IoC容器,配置类RootConfig,代码如下:

package com.xxxxf.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import redis.clients.jedis.JedisPoolConfig;

@Configuration
//定义Spring 扫描的包
@ComponentScan(value= "com.*", 
includeFilters= {@Filter(type = FilterType.ANNOTATION, value ={Service.class})})
//使用事务驱动管理器
@EnableTransactionManagement
//实现接口TransactionManagementConfigurer,这样可以配置注解驱动事务
public class RootConfig implements TransactionManagementConfigurer {

    private DataSource dataSource = null;

    /**
     * 配置数据库.
     * @return 数据连接池
     */
    @Bean(name = "dataSource")
    public DataSource initDataSource() {
        if (dataSource != null) {
            return dataSource;
        }
        Properties props = new Properties();
        props.setProperty("driverClassName", "com.mysql.jdbc.Driver");
        props.setProperty("url", "jdbc:mysql://localhost:3306/web?useUnicode=true&characterEncoding=UTF-8");
        props.setProperty("username", "root");
        props.setProperty("password", "123456");
        props.setProperty("maxActive", "200");
        props.setProperty("maxIdle", "20");
        props.setProperty("maxWait", "30000");
        try {
            dataSource = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("连接成功----------");
        return dataSource;
    }

    /***
     * 配置SqlSessionFactoryBean
     * @return SqlSessionFactoryBean
     */
    @Bean(name="sqlSessionFactory")
    public SqlSessionFactoryBean initSqlSessionFactory() {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(initDataSource());
        //配置MyBatis配置文件
        Resource resource = new ClassPathResource("mybatis/mybatis-config.xml");
        sqlSessionFactory.setConfigLocation(resource);
        return sqlSessionFactory;
    }

    /***
     * 通过自动扫描,发现MyBatis Mapper接口
     * @return Mapper扫描器
     */
    @Bean 
    public MapperScannerConfigurer initMapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.*");
        msc.setSqlSessionFactoryBeanName("sqlSessionFactory");
        msc.setAnnotationClass(Repository.class);
        return msc;
    }


    /**
     * 实现接口方法,注册注解事务,当@Transactional 使用的时候产生数据库事务 
     */
    @Override
    @Bean(name="annotationDrivenTransactionManager")
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        DataSourceTransactionManager transactionManager = 
           new DataSourceTransactionManager();
        transactionManager.setDataSource(initDataSource());
        return transactionManager;
    }


}

3.有了Spring IoC容器后,还需要配置DispatchServlet上下文,完成这个任务的便是WebConfig这个类,代码如下:

package com.xxxxf.config;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
//定义Spring MVC扫描的包
@ComponentScan(value="com.*",
includeFilters= {@Filter(type = FilterType.ANNOTATION, value = Controller.class)})
//启动Spring MVC配置
@EnableWebMvc
public class WebConfig extends AsyncConfigurerSupport { 

    /***
     * 通过注解 @Bean 初始化视图解析器
     * @return ViewResolver 视图解析器
     */
    @Bean(name="internalResourceViewResolver")
    public ViewResolver initViewResolver() {
        InternalResourceViewResolver viewResolver =new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    /**
     * 初始化RequestMappingHandlerAdapter,并加载Http的Json转换器
     * @return  RequestMappingHandlerAdapter 对象
     */
    @Bean(name="requestMappingHandlerAdapter") 
    public HandlerAdapter initRequestMappingHandlerAdapter() {
        //创建RequestMappingHandlerAdapter适配器
        RequestMappingHandlerAdapter rmhd = new RequestMappingHandlerAdapter();
        //HTTP JSON转换器
        MappingJackson2HttpMessageConverter  jsonConverter 
            = new MappingJackson2HttpMessageConverter();
        //MappingJackson2HttpMessageConverter接收JSON类型消息的转换
        MediaType mediaType = MediaType.APPLICATION_JSON_UTF8;
        List<MediaType> mediaTypes = new ArrayList<MediaType>();
        mediaTypes.add(mediaType);
        //加入转换器的支持类型
        jsonConverter.setSupportedMediaTypes(mediaTypes);
        //往适配器加入json转换器
        rmhd.getMessageConverters().add(jsonConverter);
        return rmhd;
    }

    /**
     * 异步任务处理
     * */
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(200);
        taskExecutor.initialize();
        return taskExecutor;
    }
}

4.通过上面三个类就搭建好了Spring MVC和Spring开发环境,但是没有对MyBatis进行配置,使用/mybatis/mabatis-config.xml进行配置,源码也很简单:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <mappers>
        <mapper resource="com/xxxxf/mapper/User.xml"/>
    </mappers>
</configuration>
到此我们的SSM环境也就搭建好了,现在就要去实现业务的代码了

五、实现需求代码

1.pojo层的User类,属性对应数据库表的每个字段,并且我们使用驼峰规则命名属性(这里很重要,字段userName和UserName在封装时差别很大,会映射不到mapper层的xml上),我们一贯的做法会让pojo序列化,这里虽然没有并发的情况,但是这是一种良好的做法。代码如下:

package com.xxxxf.pojo;

import java.io.Serializable;

/**
*@author xxxxf 
*2018年7月10日
*/
public class User implements Serializable{

    private static final long serialVersionUID = 89448952;
    private String userName;
    private String passWord;
    /**
     * getter && setter方法   
     */
    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;
    }
    /**
     * toString方法   
     */
    @Override
    public String toString() {
        return "user [userName=" + userName + ", passWord=" + passWord + "]";
    }



}

2.dao层中的UserDao类,这里实现我们业务和数据库直接交互的很多接口,@Repository的注解目的是持久化数据层。代码如下:

package com.xxxxf.dao;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.xxxxf.pojo.User;

/**
*@author xxxxf 
*2018年7月10日
*/
@Repository
public interface UserDao {
    /**
     * 查询用户信息   
     */
   public String getUser(@Param("userName") String userName,@Param("passWord") String passWord);
   /**
    * 增加用户  
    */
   public int addUser(User user);
   /**
    * 按主键查询用户   
    */
   public String getUserByUserName(String userName);
}

编写完dao层以后我们需要在mapper层编写User.xml实现DAO层接口方法,它相当于Dao的实现层(你可以这么理解,但是本质上有很大区别的),在User.xml我们是写了很多SQL语句与MySQL数据库进行交互,至于怎么去写SQL,举个例子:
select语句的返回值是不确定的,insert,update语句的返回值总是int(自己去思考是为什么?),所以Mybatis封装了这两种SQL语句的resultType,程序员就不用去写,这几种SQL语句参数类型也是根据方法里面的参数而决定的,两个或两个以上参数就需要用到@Param注解,MyBatis的语法我就不多赘述,有地方不理解或不清楚的自行百度,user.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.xxxxf.dao.UserDao">
    <!-- 查询用户信息 -->
    <select id="getUser" parameterType="map"
    resultType="string">
        select username as userName,password as passWord from 
        user where username=#{userName} and password=#{passWord}
    </select>
    <!--按主键查询  -->
    <select id="getUserByUserName" parameterType="string" resultType="string">
        select username as userName from user where username=#{userName}
    </select>
    <!--  public int addUser(User user); -->
    <!-- 增加用户信息 -->
    <insert id="addUser" parameterType="com.xxxxf.pojo.User" >
        insert into user(username,password) value(#{userName},#{passWord})
    </insert>
</mapper>

3.service层中的UserService类存放几个和用户相关的接口,这是是对用户而言的业务,这里有一种思想就是:用户要干嘛?我们程序员要去帮助用户实现什么接口?代码如下:

package com.xxxxf.service;

import com.xxxxf.pojo.User;

/**
*@author xxxxf 
*2018年7月10日
*/
public interface UserService {
  /**
   * 用户注册
   */
   public void  regist(User user);
   /**
    * 用户登录 
    */
   public String login(String userName,String passWord);
   /**
    * 检测用户是否存在
    */
   public String checkUser(String userName);
}

4.serviceImpl层中UserServiceImpl是UserService的实现类,@Service注解告诉Spring这是个业务层,UserService中只声明了几个接口,我们并没有去真正去实现,但是有人想为什么不直接写个实现类,反而要加一个Service层呢?这个问题,这要归结到代码复用性和维护性问题,如果你直接写一个实现,当你增加新的功能时就要在一大堆代码中是添加修改,这是非常耗时的操作,所以接口和实现分离有利于维护,代码如下:

package com.xxxxf.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.xxxxf.dao.UserDao;
import com.xxxxf.pojo.User;
import com.xxxxf.service.UserService;

/**
*@author xxxxf 
*2018年7月10日
*/
@Service
public class UserServiceImpl implements UserService{
    //依赖注入
    @Autowired
    private UserDao userDao=null;

    @Override
    //读写提交
    @Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public void regist(User user) {
        // TODO Auto-generated method stub
        userDao.addUser(user);

    }

    @Override
    //读写提交
    @Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public String login(String userName, String passWord) {
        // TODO Auto-generated method stub
        //userDao.getUser(userName, passWord);
        return userDao.getUser(userName, passWord);
    }

    @Override
    //读写提交
    @Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public String checkUser(String userName) {
        // TODO Auto-generated method stub
        return userDao.getUserByUserName(userName);
    }

}

5.控制层Controller
使用@Controller注解,然后使用@AutoWired导入service层,因为service中的方法是我们使用到的,controller通过接收前端传过来的参数进行业务操作,在返回一个指定的路径或者数据表。RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。上面讲的这些都是Spring MVC知识,如果你看不懂请百度Spring MVC流程控制,基础知识我就不多废话。这里我们的控制器类叫UserController.java,里面有两个方法,一个叫注册,另一个叫登录,具体代码如下:

package com.xxxxf.controller;



import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.util.JSONPObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.portlet.bind.annotation.ResourceMapping;
import org.springframework.web.servlet.ModelAndView;

import com.sun.java.swing.plaf.windows.resources.windows;
import com.xxxxf.dao.UserDao;
import com.xxxxf.pojo.User;
import com.xxxxf.service.UserService;

/**
*@author xxxxf 
*2018年7月10日
*/
@Controller
public class UserController {
    //依赖注入
    @Autowired
    private UserService userService=null;
    /**
     * 注册功能实现
     * */
    @RequestMapping(value="/register.do")
    @ResponseBody
    public ModelAndView regist(User user,Model model,HttpServletRequest request,HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("utf-8");//必须写在第一位,因为采用这种方式去读取数据,否则数据会出错。
        //设置这样方式去读。这样中文就能够读取出来了,但是需要注意。表单的发送方式必须是method='post'
        response.setContentType("text/html;charset=utf-8");//设置传过去的页面显示的编码
        System.out.println("#################################################");
        System.out.println("用户注册:"+"账号:"+user.getUserName()+" "+"密码:"+user.getPassWord());
        String userName=user.getUserName();
        String result=userService.checkUser(userName);
            if (result==null) {
            userService.regist(user);
            PrintWriter out = response.getWriter();
            out.print("<script language=\"javascript\">alert('注册成功!前往登录页面');window.location.href='/PersonWebSite/login.jsp'</script>");
            //model.addAttribute("msg","注册成功");
            //return new ModelAndView("redirect:/login.jsp");
            }else {
                PrintWriter out = response.getWriter();
                out.print("<script language=\"javascript\">alert('注册失败!账号已存在!');window.location.href='/PersonWebSite/register.jsp'</script>");
                //model.addAttribute("msg","账号存在,请重新注册");
                //return new ModelAndView("redirect:/register.jsp");    
            }
            return null;

    }
    /**
     * 登录功能实现
     * */
    @RequestMapping(value="/login.do")
    @ResponseBody
    public  ModelAndView login( @RequestBody User user,HttpServletRequest request,HttpServletResponse response) {
        /*Model model,HttpServletRequest request,HttpServletResponse response*/
        System.out.println("***********************************");
        String username=user.getUserName();
        //request.getParameter(username);
        String password=user.getPassWord();
        System.out.println("用户登录:"+"账号:"+username+" "+"密码:"+password);
        String result=userService.login(username, password);
        System.out.println("从数据查询结果:"+result);//查询账号密码都正确,登录成功;账号或密码错误,result=null;
        if (result != null) {
            try {
                response.getWriter().write("true");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else {
            try {
                response.getWriter().write("false");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        //model.addAttribute("msg", "登陆成功");
        return null;

    }
}

在Controller里面有一些业务流程控制,业务思想是需要你去仔细思考,比如:

        String userName=user.getUserName();
        String result=userService.checkUser(userName);
            if (result==null) {
            userService.regist(user);
            PrintWriter out = response.getWriter();
            out.print("<script language=\"javascript\">alert('注册成功!前往登录页面');window.location.href='/PersonWebSite/login.jsp'</script>");
            }else {
                PrintWriter out = response.getWriter();
                out.print("<script language=\"javascript\">alert('注册失败!账号已存在!');window.location.href='/PersonWebSite/register.jsp'</script>");
            }

这里为什么对result这个变量进行空判断,那你就得看看result是什么?奥,原来啊,reslut这个变量调用了checkUser(String userName)这个方法,这个方法去数据库查询是否有这个username是否存在,如果不存在就写进数据库里面,注册成功,如果有则前端就会提示注册失败。登录方法也用到了类似的思想,需要读者自己去揣摩思考。

至此我们的后台代码就告一段落了

六、前台代码

对于前端页面和功能的实现,我是借助于layui和jQuery这个前台框架,实际上我是个后台人员前端并不是我的强项。小伙伴在跟着这篇博客学习的时候,我会把我的整个项目的源码放到github上,源码戳这里,项目的WebContent目录下几个页面就是我们项目所需的页面(PS:如果写得不好请不要吐槽我,尽力了),当然前端页面与后台数据交互用到了JSON,还实现了AJAX技术,在页面代码里需要大家去揣摩,我就不多BB了。网页中文乱码想必是家常便饭,包括请求数据到后台乱码,前台页面展示乱码等等,这里我也解决好了,你自己去看我的项目源码,我是怎么去解决的,如果是你你会怎么去解决呢?

七、总结

写完一个项目,一定要去总结,这个项目什么地方我花费了很多时间,怎么去解决如何去解决,怎么样解决又快又好?我个人觉得思考问题本身比代码设计阶段更重要,如果没有思维过程,自己写得东西就像是套一个代码模板,下次别人换一个需求你可能就写不出来了,这也是很多刚入门的新手需要注意的地方,也是从一个码农到一个合格程序员必经之路!当然,新手刚开始只需要去多看别人写的,多去查一些资料,自己再去仿写出来就行了,久而久之你一定会有很多收获。

希望就该博客有什么问题或疑惑向我提供意见和建议,谢谢
  • 25
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值