Write at the beginning:

I am a junior student, my main language is Java, and I am going to work as an intern in Hangzhou in my senior year. This article can be considered as a souvenir, but also leave some superficial ideas for students who lack project experience (who let the subject also benefit from open source code).

Project Introduction:

This is a tourism project based on SpringBoot, there are front introduction interface, there are background management system

Required basic knowledge: Mybatis+Spring+SpringMVC+SpringBoot+Thymeleaf+ Ajax +Spring Security

The project is fully annotated, without cumbersome configuration files

Project address: github.com/anPetrichor…

At the front desk page

The front desk access address: http://localhost:8080/travel

The background page

Backstage access address: http://localhost:8080/loginManage

Java part project structure

1. Config package: contains configuration classes and aspect classes

2. Controller package: Contains the controller class

3. Dao package: Contains dao interfaces

4. Domain package: Contains entity classes

5. Service package: Contains the Service interface and interface implementation class

6. Utils package: contains the class for uploading files

1. Configuration class in the project:

Visitors need to log in to change their profile picture, improve their information and so on, which is a basic function of the website

To implement this functionality, you need to use AOP programming in Spring

LoginAOP aspect classes: You must first log in to use user action functionality

The key to aspect classes: when to add what functionality to what methods

An Aspect, “Aspect,” is understood as an enhanced function

Pointcuts are understood as a set of target methods that need to be enhanced

Advice is understood as the execution time of a section

Before using user operations, we should judge whether the user is logged in. After login, we can perform subsequent operations. If the user is not logged in, it will jump to the login page

When and where to do everything is clear, then follow the logic to write down the matter, isn’t it

@aspect @Component public class LoginAOP {// execute user function @pointcut ("execution(*) com.travel.controller.UserDoController.*(..) )") public void loginPoint(){ } @Around("loginPoint()") public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable { //1. ServletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); HttpSession session = Request.getSession (); //2. UserInfo userInfo = (userInfo) session.getAttribute("userInfo"); //3. If (userInfo == null){// If requestedWith is XMLHttpRequest, it is an Ajax request. String requestType = request.getHeader("X-Requested-With"); If ("XMLHttpRequest".equals(requestType)){// Return ajax data String loginResult = "{\"loginResult\":\"false\"}"; return loginResult; }else { return "redirect:/login"; }}else {// you have logged in to the executable target method Object proceed = joinPoint.proceed(); return proceed; }}}Copy the code

The @around surround enhancement method actually intercepts the execution of the target method, and the surround method must be executed before the target method can be executed

After the login succeeds or fails, the method can be passedAuthenticationFailureHandler.AuthenticationSuccessHandlerIf the login succeeds, the system is redirected to the background page, and if the login fails, the system is redirected to the login page

MyErrorPage implementationErrorPageRegistrarTo register different error types display different pages, the main role is to customize error pages such as 404

public void registerErrorPages(ErrorPageRegistry registry) { //400: ErrorPage errorPage_400 = new ErrorPage(HttpStatus.bad_request,"/error/400"); }Copy the code

MyMvcConfig implementationWebMvcConfigurer, the configuration class isSpringAn internal configuration mode

Instead of writing to the Controller class, you can jump to the page using addViewControllers

You can also customize the static resource mapping directory in MyMvcConfig

SpringSecurityFunction: Configure authentication information and authentication policies

You can set permissions for urls

http.authorizeRequests().antMatchers("/travel/**").permitAll()
Copy the code

UserInfoService is a custom class that is used to retrieve user information from the database.

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userInfoService);
    }
Copy the code

When AuthenticationManager authenticates the user, it obtains the user identity from the userInfoService and compares it with the user identity from HTTP. If the comparison is successful, the subsequent operations are allowed.

Entity class

(1) booking hotel table (2) round table (3) food shop table (4) destination table (5) food table (6) hotel table (7) message table (8) order table (9) permission table (10) route table (11) route picture table (12) scenery table (13) user information table

It’s a very clear system, and I won’t draw the ER diagram

Dao interface: Defines methods to operate on the database

Service interface and interface implementation class: Defines methods and method implementations

Controller class: Defines the method that handles the request

The above code is too long to mention the UserInfo operation separately

Public class UserInfo {private Integer ID; Private String username; // Private String username; // User name private String password; // User password private String phoneNum; // User phone number private String email; Private String url; // User profile address private Integer status; Private String statusStr; Private Integer gender; // Private String intro; Private List<Role> roles; // All permissions for the user //get,set // override toString}Copy the code

Just define the attributes you need

/ / @ the dao layer Mapper public interface UserInfoDao {/ / front desk travel website login @ the Select (" Select * from the user where the username = # {username} the and password=#{password}") public UserInfo findUser(@Param("username") String Username, @Param("password") String Password) throws Exception; }Copy the code

Dao layer defines a method to query the user name and password, used for the front page login, query the user name and password from the database, when the database information is consistent with the input information, the login is successful

Column =” database field name “property=” entity class attribute” and call the corresponding method using @One or @many

Public Interface UserInfoService extends UserDetailsService {public UserInfo findUser(String) extends UserDetailsService {public UserInfo findUser(String) username, String password) throws Exception; } @service public class UserInfoServiceImpl Implements UserInfoService {@resource private UserInfoDao userInfoDao; @Override public UserInfo findUser(String username,String password) throws Exception { return userInfoDao.findUser(username,password); }}Copy the code

The Service class invokes the DAO interface to implement the login function

/ / SpringSecurityController definition method to handle the login request/login/user performs operations @ RequestMapping (value = "/ login. Do", method = RequestMethod. POST) @ResponseBody public Object doLogin(@RequestParam("username") String username, @RequestParam("password") String password, HttpSession session) throws Exception{ HashMap<String,String> loginResult = new HashMap<String, String>(); UserInfo userInfo = userInfoService.findUser(username,password); if (userInfo ! = null){if (userinfo.getStatus () == 1){// The user name and password are correct and the account status is available in session.setattribute ("userInfo",userInfo); loginResult.put("loginResult","true"); }else {// Prohibit loginresult. put("loginResult","forbid"); }}else {// LoginResult. put("loginResult","false"); } return JSONArray.toJSONString(loginResult); }Copy the code

The Controller class defines the doLogin method to respond to the login.do request

The session object does:

The server creates a session object for the browser. When it needs to store user data, the server application can write the user data to the user’s browser-exclusive session. When the user accesses another application using the browser, the other application can retrieve the user’s data from the user’s session and serve the user. The login information is saved in the session, which can be used as the basis for whether the user logs in or not

Tools: Upload files

public class UploadFileUtils { public static String uploadImgFile(MultipartFile file,String param) throws IOException { / / 1. String originalFilename = file.getorigInalFilename (); String originalFilename = file.getorigInalFilename (); / / 2. Obtain the file suffix String suffixName = originalFilename. Substring (originalFilename. LastIndexOf (". ")); String newFilename = uuid.randomUuid ().toString().replace("-","") + System.currentTimemillis () + suffixName;  String localFilename = "F:\\Springboot\\18_jxnu\\ SRC \\main\\resources\\static\\images\\" + param + File.separator + newFilename; File desFile = new File(localFilename); //5. //6. Save the uploaded file with a new name to the server file.transferto (desFile); System.out.println(" Upload to server successfully "); //7. Return newFilename; //8. Return newFilename; }}Copy the code

The Spring framework uses the MultipartFile class to help you quickly implement file uploading in the form of a form

The getOriginalFileName method gets the full name of the file, including the name of the file + the extension of the file

The transferTo method is used to transfer the received file to the given destination path

Implementation steps:

The front end passes in the file, obtains the file, renames the file name, saves to the required path, saves the picture

The front page

Login page: The login page provides a message to the user when the user name or password is incorrect. After a successful login, the user is redirected to the main page

A tipString is used to prompt the user when the user name or password is blank

This is done by defining the ValidateTip function

function validateTip(element,css,tipString,status){
    element.css(css);
    element.attr("placeholder",tipString);
    element.attr("validateStatus",status);
}
Copy the code

If the user name is null, change the INPUT CSS style to red, tipString to “The user name cannot be null”, and status to false to check whether the user name is null. The same is true for the password.

var username = $("#username"); username.on("blur",function () { if (username.val() == null || username.val() == ""){ ValidateTip (username,{"border":"2px solid red"}," username ", "false"); }});Copy the code

When the login button is clicked, Ajax makes a login.do request to the server

When the result returned to the client is true, the login is successful and the current page opens /travel.

$.ajax({ type:"POST", url:"/login.do", data:{"username":username.val(),"password":password.val()}, dataType:"json", success:function (data) { if (data.loginResult == "true"){ location.href = "/travel"; }}});Copy the code

If false is returned from the client, the login failed and an error page is returned.

if (data.loginResult == "false"){ error.show(); error.css("border","2px solid #ea6f5a"); Error.html (" Incorrect user name or password "); }Copy the code

The registration page has more constraints on the length and type of the user name and password than the login page. The subject uses regular expressions to achieve this function

/ / user name regular expression, only by alphanumeric _ -, 5-16 var pattern = / ^ [a zA - Z0 - _ - 9] {5 dec} $/; / / password (6-24, including letters, Numbers, special characters [$@! #? % * &]) var pattern = / ^ [a - zA - Z0-9. $@! #? % * &] 6, 24} {$/; Regular expression var patrn = / / phone number / ^ (13 [0-9] [0-9] | | 15 18 [0-9]) \ d {8} $/;Copy the code

Use ajax requests to determine whether the user name and number are used

If it is not in use, normal registration operations can be performed

Ajax judgments are implemented in a similar way to /login.ajax above

Top navigation bar

The navigation bar is divided into two parts: the navigation bar on the left and user information on the right

Th :fragment="traveltop"// Left th:fragment="userInfo"// RightCopy the code
Th :if="${session.userinfo ==null}" th:if="${session.userinfo! =null}// Indicates that you are logged inCopy the code

If the user has logged in, the personal center page is displayed. If the user has not logged in, the original fragment is displayed

Home Page The home page uses the each loop to read data and display the results

        <div th:each="destination:${destinations}">
             <img th:src="@{${destination.url}}">
        </div>
Copy the code

The Controller layer uses the Service layer findSixDestination method to find six hot spots from the database

@RequestMapping(value = "/travel",method = RequestMethod.GET)
    public String travel(Model model) throws Exception{
        List<Destination> destinations =  destinationService.findSixDestination();
        model.addAttribute("destinations",destinations);
        return "user/travel";
    }
Copy the code

Attractions Details Page The video tag in HTML needs to be formatted to play properly

Recommended Route page

The page initiates a request, the controller calls the Service method to process the request, and the Service method in turn calls the DAO interface, which queries the database data.

@select (" Select * from route order by heat desc") @results ({@result (id = true,property = "id",column = "id"), @Result(property = "routePhotoList",column = "id",javaType = List.class,many = @Many(select = "com.travel.dao.RoutePhotoDao.findRoutePhotoByRId")) }) public abstract List<Route> findAllByHeat() throws Exception;Copy the code

Free-travel page

Fuzzy query for database information, other steps are the same as the above page

@select (" Select * from route where routeDesc like concat(concat('%',#{month},'%')) and price >= #{minPrice} and price < #{maxPrice} and time >= #{minDay} and time <= #{maxDay} and routeDesc like concat(concat('%',#{dest},'%'))")Copy the code

Hotel Booking page

@select (" Select * from hotel where destId=#{destId}")Copy the code

FindHotelsByDestName. Ajax after find the data returned to find the hotel information

search.on("click",function () { $.ajax({ type:"GET", url:"/travel/hotel/findHotelsByDestName.ajax", data:{"destName":destName.val()}, dataType:"json", success:function (data) { var str = ""; if (null ! = data && "" ! = data){ $.each(data,function (index,hotel) { str += "<div class=\"row h-item\">" + "<div class=\"col-lg-3\">" + "<img src=\"" + hotel.url + "\" class=\"img-rounded\">" + "</div>" + "<div class=\"col-lg-9\">" + "<div class=\"h-info\">" + "< h4 >" + hotel name + "< / h4 >" + "< p >" + hotel. English + "< / p >" + "< p >" + hotel. HotelDesc + "< / p >" + "< p > position: "+ hotel.location + "</p>" +" " + hotel.price + "</p>" + '<button hotelId=\"' + hotel.id + '\"' + 'hotelPrice=\"' + hotel.price + '\"' + "class=\"btn BTN - warning book - hotel \ "> reservations now < / button >" + "< / div >" + "< / div >" + "< / div >" + "< hr >"; });Copy the code

Background management system

Background management system is a visual data to add, delete and check the page

This part is so easy to write the SQL completely

When the amount of background data is large, pageHelper plug-in can be used to paging the data

Write at the end:

The writing level and code level are limited, if there are mistakes, please forgive me.