The back-end ideas of the dark horse tourism network project and the summary of common errors need the source code. Please send a private letter

Posted by intercampus on Sun, 03 Oct 2021 02:31:18 +0200

Personally, I suggest this project is quite good. There are many places to think about
Introduction to the technology and environment used

Environment configuration

Technical layer selection

  1. Web layer

    	Servlet Front end controller
    	Html View data display effect display
    	Filter filter
    	Beanutils  Data encapsulation
    	Jackson  json Serialization tool 
    
  2. Service layer

    	Javamail Mail send mail
    	Redis  nosql Memory database
    	Jedis  java of redis Client for
    
  3. Dao layer data access layer

    	Mysql database
    	Druid Database connection pool
    	JdbcTempalte  jdbc Tools for
    

The server uses Tomcat database mysql

Maven is loaded when importing the corresponding pom.xml

Filter to prevent garbled code

        //Convert parent interface to child interface
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) rep;
        //Get request method
        String method = request.getMethod();
        //Solve the problem of Chinese data garbled in post request
        if(method.equalsIgnoreCase("post")){
            request.setCharacterEncoding("utf-8");
        }
        //Processing response garbled code
        response.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(request,response);

Project structure

Registration function form display


Register.html
Using js to complete form verification
Form submission using ajax
After registration, jump to the success page

regisUserServlet
get data
Encapsulating User objects
Call service to complete registration
According to the prompt returned by the service
1. Convert the prompt information to json
2. Set the response header contenttype

After the corresponding registration form is submitted, the back-end processing core code is clear about the session domain to prevent the validation code from being invalid due to refresh

@WebServlet("/registerUserServlet")
public class RegisUserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // Verification Code
        String check = req.getParameter("check");
        // Get from session
        HttpSession session = req.getSession();
        String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
        // Clear the Session session domain and ensure that the verification code can only be used once
        session.removeAttribute("CHECKCODE_SERVER");

        // compare
        if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
            // Verification code error
            ResultInfo info = new ResultInfo();
            //  login has failed
            info.setFlag(false);
            info.setErrorMsg("Verification code error");
            // Serialize info object as json
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(info);
            resp.setContentType("application/json;charset=utf-8");
            resp.getWriter().write(json);
            return ;
        }

        Map<String, String[]> map = req.getParameterMap();
        User user = new User();
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        // Call service to complete registration
        UserService  service = new UserServiceImpl();
        boolean flag= service.regist(user);
        ResultInfo info = new ResultInfo();
        // Response results
        if(flag){
            //  login was successful
            info.setFlag(true);
        }else{
            //  login has failed
            info.setFlag(false);
            info.setErrorMsg("login has failed");
        }

        // Serialize info object as json
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(info);

        // Write json data back to the client
        // Set content type
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().write(json);
    }

After registration, a mailbox will be registered. Activation authentication requires mailbox verification

Display of tools

/**
 * Email tool class
 */

public final class MailUtils {
    private static final String USER = ""; // Sender's title, same as email address
    private static final String PASSWORD = ""; // If it is a qq mailbox, you can use the client authorization code or login password

    /**
     *
     * @param to Recipient mailbox
     * @param text Message body
     * @param title title
     */
    /* Send verification message */
    public static boolean sendMail(String to, String text, String title){
        try {
            final Properties props = new Properties();
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.host", "smtp.qq.com");

            // Sender's account number
            props.put("mail.user", USER);
            //Sender's password
            props.put("mail.password", PASSWORD);

            // Build authorization information for SMTP authentication
            Authenticator authenticator = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    // User name and password
                    String userName = props.getProperty("mail.user");
                    String password = props.getProperty("mail.password");
                    return new PasswordAuthentication(userName, password);
                }
            };
            // Create a mail session using environment properties and authorization information
            Session mailSession = Session.getInstance(props, authenticator);
            // Create mail message
            MimeMessage message = new MimeMessage(mailSession);
            // Set sender
            String username = props.getProperty("mail.user");
            InternetAddress form = new InternetAddress(username);
            message.setFrom(form);

            // Set recipient
            InternetAddress toAddress = new InternetAddress(to);
            message.setRecipient(Message.RecipientType.TO, toAddress);

            // Set message header
            message.setSubject(title);

            // Set the content body of the message
            message.setContent(text, "text/html;charset=UTF-8");
            // Send mail
            Transport.send(message);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

When the user activates again
Enter UserDaoimpl to modify and add code logic to store status and code

Background code implementation
Write RegisUserServlet
Write UserService and UserSericelmpl
Write UserDao and UserDaoImpl

Login function form display

Form submission in login page

		$(function () {
			// Bind a click event to the login button
			$("#btn_sub").click(function(){
				// Send an ajax request to submit form data
				$.post("user/login",$("#loginForm").serialize(),function (data){
					 // data : {flag:false ,errorMsg:''}
					if(data.flag){
						// Login succeeded
						location.href="index.html"
					}else{
						// Login failed
						$("#errorMsg").html(data.errorMsg);
					}
				});
			});
		});

Prompt information function of user name in index page‘

	After login, you need to save the user name to session Welcome to the back: users use
        if(u !=null && "Y".equals(u.getStatus())){
            // Login succeeded
            info.setFlag(true);
            // After successful login, the name obtained in the page will be saved into the session and displayed as the login name
            req.getSession().setAttribute("user",u);
        }
	Corresponding findUserServlet
        // Get login user from session
        Object user = req.getSession().getAttribute("user");
        // Write user back to client

        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf-8");
        mapper.writeValue(resp.getOutputStream(),user);

The login condition is that there is a user object in the session
Implementation steps
Access the servlet to destroy the session
Jump to login page

Three corresponding situations for login success judgment "
//Three login types corresponding to login
//1 there may not be a fixed user name for drinking
//2. The account and password are correct, but there is no correct activation status
//3. The account number and password are saved correctly

Optimize the servlet method for extraction
Reducing the number of servlets is now a Servlet, which is optimized into a module. A Servlet is equivalent to a table corresponding to a Servlet in the database. Different methods are provided in the Servlet to complete the user's request
Intermediate inheritance method BaseServlet
Complete the distribution of methods, get the final path method name, obtain the method object, and execute the method through reflection

    // Inherit HttpServlet and implement the corresponding service method
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // Complete the method distribution, get the method name at the end of the path, obtain the method object, and execute the method in a reflective manner
        // Get request path
        String uri=req.getRequestURI();  // user/add
        // Get method name
        String methodName = uri.substring(uri.lastIndexOf('/')+1);

        // Get Method object Method
        try {
            // Ignore access modifier get method
            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // Execution method
            // Violent reflex
            method.setAccessible(true);
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    //  The extraction of methods directly improves the use of corresponding methods and reduces the redundancy of codes
    //  Serialize the incoming object directly into json and write it back to the client
    public void writeValue(Object obj, HttpServletResponse resp) throws IOException {
        // Serialize json return
        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf-8");
        mapper.writeValue(resp.getOutputStream(),obj);
    }

    // Serialize the incoming object as a json return
    public String writeValueAsString(Object obj) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(obj);

Set character parameters and solve the problem of console garbled Code: garbled code will appear
File—Build —Maven — Runner –VM Options --Dfile.encodeing=gb2312

Classified data display function

Existing problems:
	Each refresh will request the database to load classification data, and the classification data will not change frequently,
	The pressure on the database is great. Cache is used to reduce the number of accesses to the database
	Query efficiency is high, so it is used redis Cache

Index.html contains header.html

Send an ajax request to access the server to load the real classification data
Traversal array

CateaggeoryServlet

FindAll(){
call Servlet query list
 take List Serialize collection to json return

}
CateaggeoryServlet

    private CategoryService service = new CategoryServiceImpl();
    // Query all classified data display
    public void findAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Call service to query all
        List<Category> cs = service.findAll();

        // Serialize json return
        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf-8");
        mapper.writeValue(resp.getOutputStream(),cs);

Corresponding FindAll

    // Control the display of the corresponding cid rname and the corresponding page number
    @Override
    public List<Category> findAll() {
        //  Query from redis
        //  Get jedis client
        Jedis jedis = JedisUtil.getJedis();
        //  Query the score (cid) and value (cname) in sortedset
        Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);

        List<Category> cs = null;
        //  Judge whether the query set is empty
        if (categorys == null || categorys.size() == 0) {
            //  If it is empty, you need to query from the database and store the data in redis
            //  Query from database
            cs = categoryDao.findAll();
            //  Store the collection data in the key of category in redis
            for (int i = 0; i < cs.size(); i++) {
                jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname());
            }
        } else {
            // If it is not empty, the data of set is stored in the List. The query is set, but the List set is required to return, so the conversion between sets is carried out
            cs = new ArrayList<Category>();
            for (Tuple tuple : categorys) {
                Category category = new Category();
                category.setCname(tuple.getElement());
                category.setCid((int)tuple.getScore());
                cs.add(category);
            }
        }

        return cs;

Cache optimization of classified data
After each page load, the classified data will re request the database to load, which puts great pressure on the database, and the classified data does not change frequently, so redis can be used to cache this data

Cache optimization with redis
In CategoryService
Query whether it is null from redis
yes
Access the query database for the first time and store the database in redis
no
Not the first visit
Return collection

CateoryDao
Both execute the dindAll() method

Don't forget to open redis when using it

reids  Open win+R  cd Enter the corresponding redis folder

    use  redis-server.exe redis.windows.conf
reids  Open win+R  cd Enter the corresponding redis folder

    use  redis-server.exe redis.windows.conf

    If not, use the following command

    redis-client.exe

    shutdown

    exit

    Then use the above command again

Pagination display of tourist routes
Click to find that the tourist routes seen in the future are different after different classifications. Send a many-to-one relationship between the tourist route table and the classification table by analyzing the database table structure

It is realized through the following three class functions
RouteSerlvet
RouteService
RouteDao

Select * from tab_route where cid = ? ;
Query score(cid) in Redis

'

  • <a Href ="source_list.html?cid = '+data[i].cid+'">'+data[i].cname+'
  • Passing of category id

    Redis Medium query score(cid)
    Page delivery cid
    Header.html transmit cid
    

    Display tourism route data in pages

    In the synchronization mode, you can put the data into the request field, and use the foreach tag and el expression in the jsp to traverse the data to generate data

    Html can only display foreground pages asynchronously

    Client page
    The ajax request sent by the client page requests the data of the PageBean
    Carry parameters
    currentPage (current page number)
    PageSize (number of items displayed per page)
    CID (paging cid)

    Respond and process the RouteServlet. The judgment conditions here need to be null judged to prevent the occurrence of null pointers

        public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // Accept three parameters
            String currentPageStr = request.getParameter("currentPage");
            String pageSizeStr = request.getParameter("pageSize");
            String cidStr = request.getParameter("cid");
    
            //Accept rname line name
    
            //  When obtaining the corresponding rname, you need to make corresponding conditions. No, the corresponding null pointer exception will be caused when the rname is not entered
            //  In particular, when you click the second page during pagination query, the data will not be displayed normally
            String rname = request.getParameter("rname");
    
            if(rname!= null && rname.length()>0 && !"null".equals(rname)){
                rname = new String(rname.getBytes("iso-8859-1"),"utf-8");
            }
    
            int cid = 0;//Category id
            // Handle parameters to prevent null pointer exceptions
            if(cidStr != null && cidStr.length() > 0 && !"null".equals(cidStr)){
                cid = Integer.parseInt(cidStr);
            }
    
            //The current page number. If it is not passed, it defaults to the first page
            int currentPage = 0;
            if(currentPageStr != null && currentPageStr.length() > 0  ){
                currentPage = Integer.parseInt(currentPageStr);
            }else{
                currentPage = 1;
            }
    
            //The number of records is displayed on each page. If it is not transferred, 5 records are displayed on each page by default
            int pageSize = 0;
            if(pageSizeStr != null && pageSizeStr.length() > 0  ){
                pageSize = Integer.parseInt(pageSizeStr);
            }else{
                pageSize = 5;
            }
    
            // Call service to query PageBean object
            PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize,rname);
    
            //  Serialize the pageBean object into json and return
            writeValue(pb,response);
    

    The server-side PageBean will be serialized as json and returned to the client

    // Paging object
    // Encapsulate parameters into PageBean
    public class PageBean<T> {
    
        private int totalCount;  // Total records
        private int totalPage;   // PageCount 
        private int currentPage; // Current page number
        private int pageSize;    // Number of items displayed per page
        private List<T> list;//Data set displayed per page
    

    Corresponding PgeQuery

        public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // Accept three parameters
            String currentPageStr = request.getParameter("currentPage");
            String pageSizeStr = request.getParameter("pageSize");
            String cidStr = request.getParameter("cid");
    
            //Accept rname line name
    
            //  When obtaining the corresponding rname, you need to make corresponding conditions. No, the corresponding null pointer exception will be caused when the rname is not entered
            //  In particular, when you click the second page during pagination query, the data will not be displayed normally
            String rname = request.getParameter("rname");
    
            if(rname!= null && rname.length()>0 && !"null".equals(rname)){
                rname = new String(rname.getBytes("iso-8859-1"),"utf-8");
            }
    
    
    
            int cid = 0;//Category id
            // Handle parameters to prevent null pointer exceptions
            if(cidStr != null && cidStr.length() > 0 && !"null".equals(cidStr)){
                cid = Integer.parseInt(cidStr);
            }
    
            //The current page number. If it is not passed, it defaults to the first page
            int currentPage = 0;
            if(currentPageStr != null && currentPageStr.length() > 0  ){
                currentPage = Integer.parseInt(currentPageStr);
            }else{
                currentPage = 1;
            }
    
            //The number of records is displayed on each page. If it is not transferred, 5 records are displayed on each page by default
            int pageSize = 0;
            if(pageSizeStr != null && pageSizeStr.length() > 0  ){
                pageSize = Integer.parseInt(pageSizeStr);
            }else{
                pageSize = 5;
            }
    
            // Call service to query PageBean object
            PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize,rname);
    
            //  Serialize the pageBean object into json and return
            writeValue(pb,response);
        }
    

    Fuzzy query of tourist route name

    Transfer of query parameters -------------------------- click the search button to trigger the search event

    In header.html
    Set the id binding response event for the button

     $(function () {
            // Query classification data
            // Sets the path that determines data access
            $.post("category/findAll",{},function (data) {
                var lis = ' <li class="nav-active"><a href="index.html">home page</a></li>';
                // Traversal array concatenation string
                for(var i =0; i<data.length; i++){
                    // Later, access and query the corresponding database content according to cid
                    var li = '<li><a href="route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a><li>';
                    lis += li;
                }
    
                //Mosaic collection Leaderboard
                lis+'<li><a href="favoriterank.html">Collection ranking</a></li>';
    
    
                // Set the lis string to the html content of ul
                $("#category").html(lis);
            });
    
            //  Bind the click event to the search button to get the content of the search input box
            $("#search-button").click(function () {
                // A line name is required for fuzzy matching
                var rname=$("#search_input").val();
                // Jump path for splicing
                var cid=getParameter("cid");
                    location.href="http://localhost/travel/route_list.html?cid="+cid+"&rname="+rname;
            });
        });
    

    Modify background code
    Enter CategoryServlet first and call service.findAll()
    Corresponding to entering categoryDao, call categoryDao.findAll();

            // Call service to query all
            List<Category> cs = service.findAll();
    

    Corresponding findAll

        private CategoryDao categoryDao = new CategoryDaoImpl();
    
        // Control the display of the corresponding cid rname and the corresponding page number
        @Override
        public List<Category> findAll() {
            //  Query from redis
            //  Get jedis client
            Jedis jedis = JedisUtil.getJedis();
            //  Query the score (cid) and value (cname) in sortedset
            Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);
    
            List<Category> cs = null;
            //  Judge whether the query set is empty
            if (categorys == null || categorys.size() == 0) {
                //  If it is empty, you need to query from the database and store the data in redis
                //  Query from database
                cs = categoryDao.findAll();
                //  Store the collection data in the key of category in redis
                for (int i = 0; i < cs.size(); i++) {
                    jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname());
                }
            } else {
                // If it is not empty, the data of set is stored in the List. The query is set, but the List set is required to return, so the conversion between sets is carried out
                cs = new ArrayList<Category>();
                for (Tuple tuple : categorys) {
                    Category category = new Category();
                    category.setCname(tuple.getElement());
                    category.setCid((int)tuple.getScore());
                    cs.add(category);
                }
            }
    
            return cs;
        }
    

    Query of Dao database

        // Query all corresponding data
        public List<Category> findAll() {
    
            List<Category> list = new ArrayList<>();
            try{
                String sql = "select * from tab_category";
                list = template.query(sql,new BeanPropertyRowMapper<>(Category.class));
            }catch (Exception e){
            }
            return list;
        }
    

    Return the result set and fill the corresponding data to the front position

    View details
    Route_detail.html? rid =1
    When the page number is loaded, send an ajax request to query the Route object

    View the hyperlink corresponding to the details    Then bind to the hyperlink ird
     Send when page number is loaded ajax Request query route object
    			RouteServlet
    			findOne(){
    					receive rid
    					call service query
    					transformation json return
    		}
    RouteService
    	Findone( int  rid){
    			1 according to id query route object RouteDao
    			2 according to rid Route id query Tab_route_img Set collection to route object
    			3  according to sid seller id query tab_seller Query the seller information and set it to route object 
    	}
    

    Corresponding findOne method

        public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                // Receive parameter id
                String rid = request.getParameter("rid");
                // Call the service to query the route object
                Route route = routeService.finOne(rid);
                // Convert to json and write back to the client
                writeValue(route,response);
        }
    

    Query routeService according to the corresponding rid conditions

            Route route  = routeDao.finOne(Integer.parseInt(rid));
    
            // Query the picture collection information according to the id of the route
            List<RouteImg> routeImgList = routeImgDao.finByRid(route.getRid());
    
            // Set the collection to the route object
            route.setRouteImgList(routeImgList);
            Seller seller = sellerDao.findByid(route.getSid());
            route.setSeller(seller);
    

    Visit the following three Dao s
    RouteDao
    RouteImplDao
    SellerDao

    Call three Dao

    Foreground code
    	Route_detail.html After loading in
    				obtain rid
    				send out ajax Request acquisition route object
    				Parsing object data 
    

    Tourist route collection function

    analysis

    Judge whether the current login user has collected the line
    When the page is loaded, send an ajax request to get the tag whether the user likes it or not
    Transfer line id rid
    Request the corresponding RouteServlet according to the unused button style displayed by the tag
    Get rid line id
    Gets the currently logged in user object session
    If the user object is null, set the bar uid =0

    	call FavoriteService Query delivery rid  uid
    	Writeback client flag sign
    

    FavoriteService
    isFavorite(rid , uid)
    FavoriteDao
    findByUi dan Rid(uid rid)

    Route_detai.html

    Dynamic display of collection times

    Click the button of the favorite line

    The foreground judges whether the user logs in
    If you log in, you can click the button
    No prompt is given for login
    Send AJAX request
    RouteServlet
    Get rid of the line
    Get user's uid
    Call service to add

    FavoriteServlet add method

            // Get line id
                String rid = request.getParameter("rid");
            //  Get the currently logged in user
            User user = (User) request.getSession().getAttribute("user");
            int uid;
            if(user == null){
               return ;
            }else{
                uid= user.getUid();
            }
    
            //  Call service to add
            favoriteService.add(rid,uid);
        }
    

    FavoriteDao add method

        public void add(int rid, int uid) {
                String sql = "insert into tab_favorite  value(?,?,?)";
                template.update(sql,rid,new Date(),uid);
        }
    

    Personal summary overall project
    I personally make mistakes and difficulties
    Profile version
    Corresponding null pointer error reporting exception handling
    Character input error on details case error
    Code processing of paging
    queryForObject has and can only query one piece of data. If there is no such data in the database or the data in the database is the same, an exception will be thrown
    This is mainly because there is no correct corresponding information during data query
    Throw an exception and use try catch
    The BaseServlet extracts various annotations
    First, the servlet layer calls the service layer to implement the class, calls the dao layer to look up the table, calls and executes sql statements to return the query results

    Welcome to leave a message to discuss problems

Topics: Java Maven html