1, Project import
-
Click maven on the side (if not, you can find it in view - > tool window), click the plus sign, and select the pom.xml document in the file to import
-
First preview the static page
Start mode 1:
Start mode 2: add a start mode and click the green triangle to start
2, Technology selection
-
web:
servlet: front end controller
HTML: data presentation
Filter: filter
BeanUtils: data encapsulation
Jackson: json serialization tool -
service:
Java email: sending files in Java
redis: nosql memory data
jedis: redis client of Java -
Dao
Mysql: Database
Druid: database connection pool
jdbc template: tool class of jdbc
3, Create database
4, Realize login, registration and exit
Call graph of each layer:
Registration: use js to complete form verification in html and ajax to complete form submission
Successful registration, jump to the success page
Registration failed, jump to the failed page
servlet: RegisterServlet
(0. The setting code has been completed by using the unified filter)
1. Obtain data
2. Encapsulate User objects
3. Call service to complete registration
4. According to the service return, the prompt message is:
Convert prompt to json
Set corresponding header: contentType
service:
registerUser(User user)
Call dao to query the user according to the user name
Exists, return false
Does not exist, call dao to save user information
Dao:
1. Query user information findByUsername(string username) according to user name;
2. Save user information
Asynchronous Ajax submission form:
$(this).serialize() submit the data in the form in the format of username = XXX & & password = 123
Asynchronous submission is used to obtain the data responded by the server. The foreground uses html as the view layer. It cannot directly obtain the value from the domain object related to the servlet, but only through Ajax
**
When writing, you write a stupid question wrong, resulting in the inability to access the home page, that is, the annotation name is written wrong, and the webServlet is written as webFilter, resulting in the inability to access the web page 404
**
login.jsp
Simple jquery login authentication
<script type="text/javascript"> //Check user name format function checkUsername() { var username = $("#username").val(); var reg_username = /^[A-Za-z_0-9]$/; var flag = reg_username.test(username); if(flag){ $("#username").css("border",""); } else{ alert("User name format error"); $("#username").css("border","1px solid red"); //$("#addusername").html("user name format error")// Remember to add a new html format } return flag; } //Check password format function checkPassword(){ var password = $("#password").val(); var reg_password = /^[A-Za-z_0-9]$/; var flag = reg_password.test(password); if(flag){ $("#password").css("border",""); } else{ alert("Password format error"); $("password").css("border","1px solid red"); //$("#addusername").html("user name format error")// Remember to add a new html format } return flag; } //Check for correctness when submitting $(function () { $("#form").submit(function () { if(checkPassword()&&checkUsername()){ return true; } return false; }) //When the focus is lost, judge the format $("#username").blur(checkUsername); $("#password").blur(checkPassword); }) </script>
Add a form in the body and pass the value into the Servlet
<form id="form" name="form" action="indexServlet"> <div> user name: <input type="text" id="username" name="username" placeholder="enter one user name"> </div> <div> password: <input type="text" id="password" name="password" placeholder="Please input a password"> </div> <div> <input type="submit" id="login" name="login" value="Sign in"> </div> </form>
You can use $ to receive error messages passed in the background
<!--Get the error message from the background--> <div>$</div>
LoginServlet
//Set encoding req.setCharacterEncoding("utf-8"); //Get user input data String username = req.getParameter("username"); String password = req.getParameter("password"); //Determine whether the user name and password are correct if(username.equalsIgnoreCase("zhangsan")&&password.equalsIgnoreCase("123456")){ //If the user name and password are correct, jump to the main page req.getRequestDispatcher("/home.jsp"); }else{//The user name and password are incorrect, and the error information is stored req.setAttribute("error","Wrong user name or password"); //Carry the error information and forward it to the login page req.getRequestDispatcher("/index.jsp").forward(req,resp); }
5, Mail activation of registration page
Reason: to ensure that the email filled in by the user is correct. Can push ads
Send mail: written using the emailutil tool class
Activation mail:
For the database, activation is to change the status status to the active status
Mail activation analysis:
Don't write code under return. Java reports an unreachable statement error
See connection for details: https://blog.csdn.net/qq_33915826/article/details/79246482
6, Login
After logging in, the individual user name is dynamically displayed
header.html
<script> $(function () { $.get("findUserServlet",{},function (data) { // var msg = "welcome back,"+data.name; $("#span_username").html(msg); }) }) </script>
Asynchronous interaction
When the whole page is accessed, use ajax to access the server to query the information
7, Exit
First of all, we should think about when it is called login success?
If the login is successful, there is a user in the session
Then the exit function is realized:
header.html
<a href="javascript:location='exitServlet';">sign out</a>
1. Access the servlet and destroy the session
req.getSession().invalidate();
2. Jump to the login interface, jump to the page, and use redirection (the path writing method is virtual directory)
resp.sendRedirect(req.getContextPath()+"/login.html");
8, Optimizing Servlet -- BaseServlet
Optimization method: reduce the number of servlets and optimize them into one module and one servlet
Write a module servlet to let the servlets of various functions inherit
The module servlet inherits the HTTP servlet
"this" – who calls me and who I represent
The error report indicates that there is no matching method:
Reason: the method is declared as protected and does not have permission when accessing
resolvent:
① Ignore the access permission modifier when accessing. This method will ignore all methods
//Ignore access modifier Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //Execution method //Violent reflex method.setAccessible(true); method.invoke(this,req,resp);
② Directly change the method permission modifier to public, which is conducive to the protection of other private methods
Another low-level error was made - the findOne name was written incorrectly, causing the browser to not find it
9, Display of tourism data
Classified data display:
It turned out to be false data, which was dynamically generated from the background in the later stage
<div> <ul> <li><a href="index.html">home page</a></li> <li><a href="route_list.html">admission ticket</a></li> <li><a href="route_list.html">hotel</a></li> <li><a href="route_list.html">Hong Kong Ticket</a></li> <li><a href="route_list.html">Outbound travel</a></li> <li><a href="route_list.html">Domestic tour</a></li> <li><a href="route_list.html">Hong Kong and Macao tour</a></li> <li><a href="route_list.html">Group customization</a></li> <li><a href="route_list.html">Global free travel</a></li> <li><a href="favoriterank.html">Collection ranking</a></li> </ul> </div>
Information in database:
Code optimization: after each page loading, the page classification data will require the database to load again, which will put great pressure on the database, and the classified data will not change frequently, so redis can be used to cache this data.
The order in which the data is expected to be stored in the database is the data displayed
10, Tourism routes are displayed in different pages
After clicking on different categories, the tourist routes are inconsistent.
Classification and tourist routes are one to many
How to carry cid:
//Background service Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1); //2. Judge whether the query set is empty List<Category> cs=null; //2.1 is null, first visit if(categorys==null||categorys.size()==0){ //Query from database cs = categoryDao.findAll(); //Store the collection in the key of the category in redis for (int i = 0; i < cs.size(); i++) { //Storage zadd jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname()); } }else{ //2.2 if it is not empty, save the set data into the list //The front end needs List, but this method returns set for format conversion cs=new ArrayList<Category>(); for (Tuple tuple:categorys) { Category category = new Category(); category.setCname(tuple.getElement()); category.setCid((int)tuple.getScore()); cs.add(category); } }
front end:
for(var i=0;i<data.length;i++){ var li = '<li><a href="favoriterank.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>'; lis += li; }
How to get cid:
<script> $(function () { var search = location.search; //alert(search); //Cut the obtained string [? cid=5] to get 5 var cid = search.split("=")[1]; }) </script>
Obtain different travel route data according to cid:
11, Tourist route name query
1. Transfer of query parameters
From route_list?cid=5 pass route_list?cid=5&rname=xxx
Pass xxx
First, get the rname entered by the user
/*header.html*/ $("#search-button").click(function () { //The background performs fuzzy matching according to this name var rname = $("#search_input").val(); //alert(rname); var cid = getParameter("cid"); //alert(cid); //Jump path http://localhost/travel/route_list.html?cid=5 //Then splice rname=xxx location.href="http://localhost/travel/route_list.html?cid="+cid+"&rname="+rname; })
/*route_list.html*/ //The getParameter() method encapsulates the character cutting function for itself //Get cid var cid = getParameter("cid"); //Get rname var rname = getParameter("rname"); if(rname){ //Decoding method. The obtained rname is a url and needs to be decoded rname=window.decodeURIComponent(rname); }
2. Modify the previous background code
Servlet,Service,Dao
tomcat7 transfers the value from the front end to the background. The solution is:
//Tomcat7, the get request is garbled rname = new String(rname.getBytes("iso-8859-1"),"utf-8");
There is a problem that data cannot be queried by directly clicking the relevant route to switch the route:
Pass value load(5,2, 'null')
Solution link
When rname is empty, the "null" string passed to RouteServlet by the front end is not null
Therefore, in the place of judging whether the parameter in RouteDaoImpl has a value, rname is queried as a "null" keyword (with a value), while the database does not have a tourism route with a keyword of "null", so 0 records are returned, resulting in an error.
It is similar to the previous judgment that cid is' null '.
12, View tour route details
Error in picture display:
Through front-end breakpoint debugging, it is found that the tag uses the style="display:none; attribute
If its attribute is deleted, the picture can be displayed normally, but the displayed data css is incorrect
Judge i that there are 4 displays on each page, and more than 4 are hidden
//Traverse routeImgList for (var i = 0; i < route.routeImgList.length; i++) { if(i>=4){ var astr='<a title="" data-bigpic="'+route.routeImgList[i].bigPic+'" style="display:none;">\n' + ' <img src="'+route.routeImgList[i].smallPic+'">\n' + ' </a>' }else { var astr='<a title="" data-bigpic="'+route.routeImgList[i].bigPic+'" >\n' + ' <img src="'+route.routeImgList[i].smallPic+'">\n' + ' </a>' } ddstr+=astr; }
13, Tourist route collection function
After the page is loaded, send an ajax request to query the database to see whether the user has collected the line
Display different styles according to query results
Dynamic display of collection words
Click the favorite button:
Bind the click event to the button, click the button, and call the addFavorite() method in js:
<a id="favorite" onclick="addFavorite();"><i ></i>Click collection</a>