一、环境搭建
1.便于查询JSON数据
为了便于查询JSON数据,隐藏没有值的属性,减少流量的消耗,服务器不应该向客户端响应为NULL的属性。可以在属性或类之前添加@JsonInclude(value=Include.NON_NULL),也可以在application.properties中添加全局的配置。
# 服务器向客户端不响应为null的属性
spring.jackson.default-property-inclusion=NON_NULL
2.开启sql映射
mybatis:
configuration:
map-underscore-to-camel-case: true
二、Entity
实体类为什么要实现Serializable
将对象转变成一串由二进制字节组成的数组,可以通过将二进制数据保存到磁盘或者传输网络,磁盘或者网络接收者可以在对象的属类的模板上来反序列化类的对象,达到对象持久化的目的。
三、Mapper
@MapperScan
MyBatis与Spring整合后需要实现实体和数据表的映射关系。实现实体和数据表的映射关系可以在Mapper接口上添加@Mapper注解。
但建议以后直接在SpringBoot启动类中加@MapperScan(“mapper包”) 注解,这样会比较方便,不需要对每个Mapper都添加@Mapper注
解。
```java
@SpringBootApplication
@MapperScan("com.cy.store.mapper")
public class StoreApplication {
public static void main(String[] args) {
SpringApplication.run(StoreApplication.class, args);
}
}
四、Service
1.异常规划
为了便于统一管理自定义异常,应先创建com.cy.store.service.ex.ServiceException自定义异常的基
类异常,继承自RuntimeException类,并从父类生成子类的五个构造方法。
package com.cy.store.service.ex;
/** 业务异常的基类 */
public class ServiceException extends RuntimeException {
// Override Methods...
}
2.测试类注解
@RunWith(SpringRunner.class)
@SpringBootTest
五、Controller
1@RequestMapping与@GetMapping和@PostMapping
从命名约定我们可以看到每个注释都是为了处理各自的传入请求方法类型,即@GetMapping用于处理请求方法的GET类型,@ PostMapping用于处理请求方法的POST类型等。
如果我们想使用传统的@RequestMapping注释实现URL处理程序,那么它应该是这样的:
@RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)
新方法可以简化为:
@GetMapping("/get/{id}")
用两种方式都可以,新的方式更为简洁方便。
2.创建响应结果类
创建com.cy.store.util.JsonResult响应结果类型。
package com.cy.store.util;
import java.io.Serializable;
/**
* 响应结果类
* @param <E> 响应数据的类型
*/
public class JsonResult<E> implements Serializable {
/** 状态码 */
private Integer state;
/** 状态描述信息 */
private String message;
/** 数据 */
private E data;
public JsonResult() {
super();
}
public JsonResult(Integer state) {
super();
this.state = state;
}
/** 出现异常时调用 */
public JsonResult(Throwable e) {
super();
// 获取异常对象中的异常信息
this.message = e.getMessage();
}
public JsonResult(Integer state, E data) {
super();
this.state = state;
this.data = data;
}
// Generate: Getter and Sette
}
3.@ExceptionHandler
用于统一处理方法抛出的异常。当我们使用这个注解时,需要定义一个异常的处理方法,再给这个方法加上@ExceptionHandler注解,这个方法就会处理类中其他方法(被@RequestMapping注解)抛出的异常。@ExceptionHandler注解中可以添加参数,参数是某个异常类的class,代表这个方法专门处理该类异常。
package com.cy.store.controller;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.ServiceException;
import com.cy.store.service.ex.UsernameDuplicateException;
import com.cy.store.util.JsonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
/** 控制器类的基类 */
public class BaseController {
/** 操作成功的状态码 */
public static final int OK = 200;
/** @ExceptionHandler用于统一处理方法抛出的异常 */
@ExceptionHandler(ServiceException.class)
public JsonResult<Void> handleException(Throwable e) {
JsonResult<Void> result = new JsonResult<Void>(e);
if (e instanceof UsernameDuplicateException) {
result.setState(4000);
} else if (e instanceof InsertException) {
result.setState(5000);
}
return result;
}
}
如:
在类中添加处理请求的用户注册方法。
@RequestMapping("reg")
public JsonResult<Void> reg(User user) {
// 创建返回值
JsonResult<Void> result = new JsonResult<Void>();
try {
// 调用业务对象执行注册
userService.reg(user);
// 响应成功
result.setState(200);
} catch (UsernameDuplicateException e) {
// 用户名被占用
result.setState(4000);
result.setMessage("用户名已经被占用");
} catch (InsertException e) {
// 插入数据异常
result.setState(5000);
result.setMessage("注册失败,请联系系统管理员");
}
return result;
}
简化UserController控制器类中的用户注册reg()方法的代码。
/** 处理用户相关请求的控制器类 */
@RestController
@RequestMapping("users")
public class UserController extends BaseController {
@Autowired
private IUserService userService;
@RequestMapping("reg")
public JsonResult<Void> reg(User user) {
// 调用业务对象执行注册
userService.reg(user);
// 返回
return new JsonResult<Void>(OK);
4.session处理
session对象主要存在服务器端,可以用于保存服务器的临时数据,所保存的数据可以在整个项目中通过访问获取,把session看成一个共享的数据。
如:首次登录的用户数据,转移到session对象中
session.getAttrbute(“key”)
1.在父类BaseController中添加从HttpSession对象中获取uid和username的方法,以便于后续快捷的获
取这两个属性的值。
/**
* 从HttpSession对象中获取uid
* @param session HttpSession对象
* @return 当前登录的用户的id
*/
protected final Integer getUidFromSession(HttpSession session) {
return Integer.valueOf(session.getAttribute("uid").toString());
}
/**
* 从HttpSession对象中获取用户名
* @param session HttpSession对象
* @return 当前登录的用户名
*/
protected final String getUsernameFromSession(HttpSession session) {
return session.getAttribute("username").toString();
}
2.重新构建login()方法,登录成功后将uid和username存入到HttpSession对象中。
服务器本身自动创建有session对象,是一个全局的session,我们获取使用即可。
SpingBoot直接使用session对象,直接将HttpSession类型的对象作为请求处理方法的参数,会自动将全局的session对象注入到请求处理方法的session形参上。
@RequestMapping("login")
public JsonResult<User> login(String username, String password, HttpSession
session) {
// 调用业务对象的方法执行登录,并获取返回值
User data = userService.login(username, password);
//登录成功后,将uid和username存入到HttpSession中
session.setAttribute("uid", data.getUid());
session.setAttribute("username", data.getUsername());
// System.out.println("Session中的uid=" + getUidFromSession(session));
// System.out.println("Session中的username=" +
getUsernameFromSession(session));
// 将以上返回值和状态码OK封装到响应结果中并返回
return new JsonResult<User>(OK, data);
}
5.拦截器
分析:项目中很多操作都是需要先登录才可以执行的,如果在每个请求处理之前都编写代码检查
Session中有没有登录信息,是不现实的。所以应使用拦截器解决该问题。
addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
excludePathPatterns:用于设置不需要拦截的过滤规则
(1)创建拦截器类com.cy.store.interceptor.LoginInterceptor,并实现org.springframework.web.servlet.HandlerInterceptor接口。
package com.cy.store.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** 定义处理器拦截器 */
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {
if (request.getSession().getAttribute("uid") == null) {
response.sendRedirect("/web/login.html");
return false;
}
return true;
}
}
(2)创建LoginInterceptorConfigurer拦截器的配置类并实现org.springframework.web.servlet.config.annotation.WebMvcConfigurer接口,配置类需要添加@Configruation注解修饰。
package com.cy.store.config;
import com.cy.store.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/** 注册处理器拦截器 */
@Configuration
public class LoginInterceptorConfigurer implements WebMvcConfigurer {
/** 拦截器配置 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
会话
1.重新构建login()方法,登录成功后将uid和username存入到HttpSession对象中。
2.在父类BaseController中添加从HttpSession对象中获取uid和username的方法,以便于后续快捷的获
取这两个属性的值。
// 创建拦截器对象
HandlerInterceptor interceptor = new LoginInterceptor();
// 白名单
List<String> patterns = new ArrayList<String>();
patterns.add("/bootstrap3/**");
patterns.add("/css/**");
patterns.add("/images/**");
patterns.add("/js/**");
patterns.add("/web/register.html");
patterns.add("/web/login.html");
patterns.add("/web/index.html");
patterns.add("/web/product.html");
patterns.add("/users/reg");
patterns.add("/users/login");
patterns.add("/districts/**");
patterns.add("/products/**");
// 通过注册工具添加拦截器
registry.addInterceptor(interceptor).addPathPatterns("/**").excludePathPatterns
(patterns);
}
}
六、前端页面
1.发送请求ajax
$("#btn-reg").click(function() {
console.log($("#form-reg").serialize());
$.ajax({
url: "/users/reg",
type: "POST",
data: $("#form-reg").serialize(),
dataType: "json",
success: function(json) {
if (json.state == 200) {
alert("注册成功!");
// location.href = "login.html";
} else {
alert("注册失败!" + json.message);
}
}
});
});
2.接收请求axios(ajax)
axios
.get("/main/barChart")
.then((res) => {
var result = res.data
this.setBarchrt(result.classifiedName,result.priceAbnormalNums,result.salesAbnormalNums,result.bothAbnormalNums
})
.catch((err) => {
console.info("报错的信息", err.response.message)
});
3.session
session对象主要存在服务器端,可以用于保存服务器的临时数据,所保存的数据可以在整个项目中通过访问获取,把session看成一个共享的数据。