Preparation before development
Prepare data sheet
Combined with the page prototype to create the database reggie
, you can use the graphical interface or MySQL command to run the SQL file to import the table structure (do not place the sql file in the Chinese directory when using the command)
Create project
Create a SpringBoot project (check Spring Web, MySQL and MyBatis)
, configure the pom.xml file to import the coordinates of druid, lombok and MyBatisPlus dependencies
>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
Configure applicaton.yml file
server: port: 8080 spring: application: # The name of the web application (the default is the project name) name: reggie_take_out datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai & amp;useUnicode=true & amp;characterEncoding=utf-8 & amp;zeroDateTimeBehavior=convertToNull & amp;useSSL=false & amp;allowPublicKeyRetrieval= true username: root password: 123456 redis: host: localhost port: 6379 database: 0 cache: redis: time-to-live: 1800000 #ms ->30min mybatis-plus: configuration: # When mapping entities or attributes, remove the underscores from table names and field names in the database, and enable mapping according to camel case naming (default is true) map-underscore-to-camel-case: true # Enable logging function log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: ASSIGN_ID reggie: path: D:\SpringBoot_Reggie\reggie_take_out\src\main\resources\static\front\hello\
Create the main program class and use the @SpringBootApplication annotation
to tell SpringBoot that this is a SpringBoot application and is the startup entry point for all programs
@Slf4j @SpringBootApplication public class MainApplication {<!-- --> public static void main(String[] args) {<!-- --> SpringApplication.run(MainApplication.class, args); log.info("Project started successfully..."); } }
Create a method to handle the request in the request controller
@Slf4j @RestController public class HelloController {<!-- --> @RequestMapping("/hello") public String handle01(@RequestParam("name") String name){<!-- --> log.info("The request came in...."); return "Hello, Spring Boot 2!" + "Hello:" + name; } }
Static resource mapping
Static resources introduced in the Spring Boot project need to be placed in the static or templates
directory before they can be accessed
- To access the static resources in the resources directory, you need to write the configuration class
config/WebMvcConfig
to configure theresource mapping
to release these resources.
Open the browser to access the login page (cannot log in yet) http://localhost:8080/backend/page/login/login.html
@Configuration @Slf4j public class WebMvcConfig extends WebMvcConfigurationSupport {<!-- --> @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) {<!-- --> log.info("Start static resource mapping..."); //Map to the corresponding requested resource directory according to the user's request path registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); } }
Unified result packaging
Write a common result class common/Result
to encapsulate the return results of all Controllers. All data that the server responds to the front end will eventually be packaged in this type
@Data @AllArgsConstructor @NoArgsConstructor public class Result<T> {<!-- --> private Integer code; // Encoding: 1 succeeds, 0 and other numbers fail private String errMsg; // Error message private T data; // Data (such as response entity class data) private Map map = new HashMap(); // dynamic data public static <T> Result<T> success(T data) {<!-- --> Result<T> r = new Result<>(); r.code = 1; //Success status code r.data = data; return r; } public static <T> Result<T> error(String errMsg) {<!-- --> Result<T> r = new Result<>(); r.errMsg = errMsg; //Set error message r.code = 0; //Default failure status code, we can set other status codes according to our needs later. return r; } public Result<T> add(String msg, String value) {<!-- --> this.map.put(msg, value); return this; } }
Login and logout functions
Front-end login and logout effect
new Vue({<!-- --> methods: {<!-- --> async handleLogin() {<!-- --> // Verify whether the username and password are empty. validate is the verification method provided by the element framework. this.$refs.loginForm.validate(async (valid) => {<!-- --> if (valid) {<!-- --> // Render the login status, true means logging in this.loading = true // res is the result of the server response (usually a general result encapsulation class) let res = await loginApi(this.loginForm) if (String(res.code) === '1') {<!-- -->// 1 indicates successful login localStorage.setItem('userInfo',JSON.stringify(res.data))// data represents entity class data window.location.href= '/backend/index.html' } else {<!-- --> this.$message.error(res.msg) this.loading = false } } }) logout() {<!-- --> logoutApi().then((res)=>{<!-- --> if(res.code === 1){<!-- --> localStorage.removeItem('userInfo') window.location.href = '/backend/page/login/login.html' } }) }, } } }) <div class="right-menu"> <!--The logged-in username is dynamically displayed here--> <div class="avatar-wrapper">{<!-- -->{<!-- --> userInfo.name }}</div> <!--Here is the logout button--> <img src="images/icons/[email protected]" class="outLogin" alt="Exit" @click="logout" /> </div> <div class="right-menu"> // userInfo is the user information that the backend responds to after successful login. <div class="avatar-wrapper">{<!-- -->{<!-- --> userInfo.name }}</div> <img src="images/icons/[email protected]" class="outLogin" alt="Exit" @click="logout" /> </div> function loginApi(data) {<!-- --> return $axios({<!-- --> 'url': '/employee/login', 'method': 'post', data }) } function logoutApi(){<!-- --> return $axios({<!-- --> 'url': '/employee/logout', 'method': 'post', }) }
Login and logout business process
Step 1: Create the corresponding entity class Employee
@Data public class Employee implements Serializable {<!-- --> private static final long serialVersionUID = 1L; private Long id; private String username; private String name; private String password; private String phone; private String sex; private String idNumber; private Integer status; private LocalDateTime createTime; private LocalDateTime updateTime; // Don’t worry about these two for now, we’ll talk about them later. @TableField(fill = FieldFill.INSERT) private Long createUser; @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser; }
Step 2: Create the corresponding Mapper and Service
// Directly hand over the proxy class dynamically generated by the Mapper interface to the Spring container management (no need to scan the mapper interface again) @Mapper public interface EmployeeMapper extends BaseMapper<Employee> {<!-- --> }
public interface EmployeeService extends IService<Employee> {<!-- --> } //Inherit ServiceImpl to implement the EmployeeService interface, don't forget the @Service annotation @Service public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {<!-- --> }
Step 3: Write Login method
in Controller
@RestController @RequestMapping("/employee") public class EmployeeController {<!-- --> @Autowired private EmployeeService employeeService; /** * Login function * @param request * @param employee * @return */ // The login page sends a post request to submit the user name and password. @PostMapping("/login") // Encapsulate the username and password submitted by the page into the Employee object public Result<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {<!-- --> String password = employee.getPassword(); // The tool class provided inside spring can encrypt the password with MD5 password = DigestUtils.md5DigestAsHex(password.getBytes()); //Query the database based on the username submitted on the page LambdaQueryWrapper<Employee> lqw = new LambdaQueryWrapper<>(); lqw.eq(Employee::getUsername, employee.getUsername()); Employee emp = employeeService.getOne(lqw); // If no employee is found, a login failure result will be returned. if (emp == null) {<!-- --> return Result.error("Login failed"); } // Compare with the queried employee password, if inconsistent, return the result of login failure. if (!emp.getPassword().equals(password)) {<!-- --> return Result.error("Login failed"); } // Check the status of the queried employee. If it is disabled, return the result that the employee is disabled. if (emp.getStatus() == 0) {<!-- --> return Result.error("This user has been disabled"); } // If the login is successful, store the employee ID in the Session and return the login result. request.getSession().setAttribute("employee",emp.getId()); return Result.success(emp); } }
Step 4: Write Exit method
in Controller
/** * Logout function * @param request * @return */ @PostMapping("/logout") public Result<String> logout(HttpServletRequest request) {<!-- --> // Clean up the ID of the currently logged-in employee saved in the Session request.getSession().removeAttribute("employee"); //return results return Result.success("Exit successfully"); }
Login status verification
It is obviously unreasonable for us to directly access http://localhost/backend/index.html and still access the homepage normally without logging in, so we need to use filter or interceptor
Use filter or interceptor
to determine whether the user is logged in. Only when the user is logged in successfully can you see the home page. If not logged in, the user will be redirected to the login page
Step 1: Set the filter, /*
means processing all requests
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*") @Slf4j public class LoginCheckFilter implements Filter {<!-- --> //Tool class provided by Spring, specifically used for path matching public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher(); @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {<!-- --> // force transfer HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //1. Get the URI of this request String requestURI = request.getRequestURI(); // Output the intercepted URI to the log. {} is a placeholder that will automatically fill in the content of request.getRequestURI() log.info("Intercepted request: {}",requestURI); // Define all requests that do not need to be processed String[] urls = new String[]{<!-- --> "/employee/login", "/employee/logout", // Requests to access static pages in the backend and front directories do not need to be intercepted, but data rendered through Ajax requests in the page needs to be intercepted. "/backend/**", "/front/**" }; //2. Determine whether this request needs to be processed boolean check = check(urls, requestURI); //3. If no processing is required, release it directly. if (check) {<!-- --> log.info("This request: {}, no need to process", requestURI); filterChain.doFilter(request,response); return; } //4. For requests that need to be processed, the login status needs to be determined. If logged in, the request will be released directly. if (request.getSession().getAttribute("employee") != null) {<!-- --> log.info("The user has logged in, the id is {}",request.getSession().getAttribute("employee")); filterChain.doFilter(request,response); return; } //5. If not logged in, return a Result object and msg is NOTLOGIN log.info("The user is not logged in"); // , // Import the coordinates of fastjson, convert the Result object into a string in Json format, and then respond to the client through the output stream. response.getWriter().write(JSON.toJSONString(Result.error("NOTLOGIN"))); } public boolean check(String[] urls, String requestURI){<!-- --> for (String url : urls) {<!-- --> boolean match = PATH_MATCHER.match(url, requestURI); if (match) {<!-- --> //match return true; } } //Mismatch return false; } }
Step 2: The front-end sets a response interceptor
, obtains the user information of the back-end response, and automatically redirects to the login page if the user is not logged in
//Response interceptor service.interceptors.response.use(res => {<!-- --> if (res.data.code === 0 & amp; & amp; res.data.msg === 'NOTLOGIN') {<!-- -->// Return to the login page console.log('---/backend/page/login/login.html---') localStorage.removeItem('userInfo') // Jump to the login page window.top.location.href = '/backend/page/login/login.html' } else {<!-- --> return res.data } }