BaseController
1、复用基础常见操作
BaseController 使用并不算普遍,有些项目会使用,有些不会,因为有些小功能也完全可以使用工具类实现。
package com.xiaocai.mybatistk.common.base;
import com.xiaocai.mybatistk.common.message.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
/**如果有一些比较通用的操作可以放这里,
* 当然 BaseController 的并不多,因为这些小功能也完全可以使用工具类实现。
* 这些方法随便一搜都能找到,这里列举一部分
* @author xiaocai.zhang
*/
@Slf4j
public class BaseController {
/**
* 从请求头中获取token
*
* @return
*/
public String getTokenFromHeader() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return requestAttributes.getRequest().getHeader("token");
}
/**
* 获取请求的ip地址
*
* @return
*/
protected final String getIpAddr() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String ip = request.getHeader("x-forwarded-for");
if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
/**
* 从thread local获取网络上下文
*/
public HttpServletRequest getServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes;
if (requestAttributes instanceof ServletRequestAttributes) {
servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
return servletRequestAttributes.getRequest();
}
return null;
}
/**
* 获取当前客户端session对象
* @return
*/
public HttpSession getSession() {
return getServletRequest().getSession();
}
public HttpServletRequest getRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
public HttpServletResponse getResponse() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 设置 cookie
*
* @param cookieName
* @param value
* @param age
*/
protected void setCookie(String cookieName, String value, int age) {
Cookie cookie = new Cookie(cookieName, value);
cookie.setMaxAge(age);
// cookie.setHttpOnly(true);
getResponse().addCookie(cookie);
}
/**
* 保存信息到request中
*
* @param key
* @param value
*/
public void setRequestAttribute(String key, Object value) {
this.getRequest().setAttribute(key, value);
}
protected String getCookie(String cookieName) {
Cookie[] cookies = getRequest().getCookies();
for (Cookie cookie : cookies) {
if (cookieName.equals(cookie.getName())) {
return cookie.getValue();
}
}
return null;
}
/**
* 请求方式判断
*
* @param request
* @return
*/
public boolean isAjaxRequest(HttpServletRequest request) {
if (!(request.getHeader("accept").indexOf("application/json") > -1
|| (request.getHeader("X-Requested-With") != null
&& request.getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1)
|| "XMLHttpRequest".equalsIgnoreCase(request.getParameter("X_REQUESTED_WITH")))) {
return false;
}
return true;
}
}
2、钩子方法使用
有时候,有一些通用的数据校验、权限验证、安全验证,分页信息,可以使用通用controller来实现,当然可以使用拦截器或者过滤器来实现。
但有时候对某些业务需要进行特殊处理,比如前置处理,特殊业务特殊验证等,这时候来个baseController是最开心的时候了。
我们可以在 BaseController
中开心的定义执行模板,和钩子方法,有没有发现,这不就是设计模式里的模板模式吗? 自己曾经玩过,竟然后知后觉…
好吧,面试的时候再也不能说自己没有用过设计模式了…
比如:
package com.xiaocai.mybatistk.common.base;
import com.xiaocai.mybatistk.common.message.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
/**如果有一些比较通用的操作可以放这里,
* 当然 BaseController 的并不多,因为这些小功能也完全可以使用工具类实现。
* @author xiaocai.Zhang
*/
@Slf4j
public class BaseController {
protected void before(HashMap<String,Object> params){
log.info("这里进行一些通用业务的前置处理--common--before");
}
protected void after(HashMap<String,Object> params){
log.info("这里进行一些通用业务的后置处理--common--after");
}
/**
* 需要进行前置后置处理的方法
* @param params
*/
protected CommonResult doSomeBusiness(HashMap<String,Object> params){
before(params);
doBusiness(params);
after(params);
return CommonResult.ok("事情搞定了");
}
protected void doBusiness(HashMap<String,Object> params) {
log.info("这里进行一些通用业务的处理--common--doBusiness--start");
String ip = getIpAddr(); // 方法就不重复贴出来了
log.info("ip--{}", ip);
String tokenFromHeader = getTokenFromHeader(); // 方法就不重复贴出来了
log.info("token--{}", tokenFromHeader);
log.info("这里进行一些通用业务的处理--common--doBusiness--end");
}
}
通用的定义好了,那怎么使用呢?
使用,定义一个自己的业务类,我就用之前的UserContrller
了:
package com.xiaocai.mybatistk.controller;
import com.xiaocai.mybatistk.common.base.BaseController;
import com.xiaocai.mybatistk.common.message.CommonResult;
import com.xiaocai.mybatistk.model.User;
import com.xiaocai.mybatistk.service.base.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
/**
* @author Xiaocai.Zhang
*/
@Slf4j
@RestController
public class UserController extends BaseController {
@Autowired
private UserService userService;
/**
* http://localhost:8804/userList
* @param user
* @return
*/
@RequestMapping("/userList")
public CommonResult getUserList(User user) {
user.setName("J");
user.setEmail("test");
List<User> result = userService.getList(user);
return CommonResult.ok(result);
}
/**
* http://localhost:8804/user?userId=1
* @param userId
* @return
*/
@RequestMapping("/user")
public CommonResult getUserList(@RequestParam Integer userId) {
User result = userService.getUserById(userId);
return CommonResult.ok(result);
}
@Override
protected void before(HashMap<String, Object> params) {
super.before(params);
log.info("这里进行一些自己业务的前置处理--user--before");
}
@Override
protected void after(HashMap<String, Object> params) {
super.after(params);
log.info("这里进行一些自己的业务处理--user--after");
}
/**
* http://localhost:8804/dothing
* @param params
* @return
*/
@Override
@RequestMapping("/dothing")
public CommonResult doSomeBusiness(HashMap<String, Object> params) {
super.doSomeBusiness(params);
return CommonResult.ok("事情搞定了");
}
@Override
protected void doBusiness(HashMap<String, Object> params) {
super.doBusiness(params);
log.info("这里进行一些自己的业务处理--user--搞自己的事情");
}
}
为了方便查看,我把结果搞短一点,通用的调用结果:
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : 这里进行一些通用业务的前置处理--common--before
INFO 20328 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己业务的前置处理--user--before
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : 这里进行一些通用业务的处理--common--doBusiness--start
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : ip--0:0:0:0:0:0:0:1
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : token--null
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : 这里进行一些通用业务的处理--common--doBusiness--end
INFO 20328 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己的业务处理--user--搞自己的事情
INFO 20328 --- [nio-8804-exec-1] c.x.m.common.base.BaseController : 这里进行一些通用业务的后置处理--common--after
INFO 20328 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己的业务处理--user--after
效果处理了吧?
有人就要说了,既然是特殊业务可不可以不要调用通用处理,只做自己业务的前置和后置处理?
当然可以!!!
把三个super
的调用注释掉就可以。 注意,千万不要把模板方法的supper 干掉了,如果你干掉了super.doBusiness(params);
的模板方法就变成了普通请求,不能调用 before()
和 after()
了。
package com.xiaocai.mybatistk.controller;
import com.xiaocai.mybatistk.common.base.BaseController;
import com.xiaocai.mybatistk.common.message.CommonResult;
import com.xiaocai.mybatistk.model.User;
import com.xiaocai.mybatistk.service.base.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
/**
* @author Xiaocai.Zhang
*/
@Slf4j
@RestController
public class UserController extends BaseController {
@Autowired
private UserService userService;
/**
* http://localhost:8804/userList
* @param user
* @return
*/
@RequestMapping("/userList")
public CommonResult getUserList(User user) {
user.setName("J");
user.setEmail("test");
List<User> result = userService.getList(user);
return CommonResult.ok(result);
}
/**
* http://localhost:8804/user?userId=1
* @param userId
* @return
*/
@RequestMapping("/user")
public CommonResult getUserList(@RequestParam Integer userId) {
User result = userService.getUserById(userId);
return CommonResult.ok(result);
}
@Override
protected void before(HashMap<String, Object> params) {
//super.before(params);
log.info("这里进行一些自己业务的前置处理--user--before");
}
@Override
protected void after(HashMap<String, Object> params) {
//super.after(params);
log.info("这里进行一些自己的业务处理--user--after");
}
/**
* http://localhost:8804/dothing
* @param params
* @return
*/
@Override
@RequestMapping("/dothing")
public CommonResult doSomeBusiness(HashMap<String, Object> params) {
super.doSomeBusiness(params);
return CommonResult.ok("事情搞定了");
}
@Override
protected void doBusiness(HashMap<String, Object> params) {
//super.doBusiness(params);
log.info("这里进行一些自己的业务处理--user--搞自己的事情");
}
}
执行结果:
2020-12-01 17:44:34.074 INFO 1540 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己业务的前置处理--user--before
2020-12-01 17:44:34.074 INFO 1540 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己的业务处理--user--搞自己的事情
2020-12-01 17:44:34.074 INFO 1540 --- [nio-8804-exec-1] c.x.mybatistk.controller.UserController : 这里进行一些自己的业务处理--user--after
完美!
3、通用的CURD 操作
要做通用的CURD操作,这个应该用的更少了,基本上会和通用的BaseService、 通用的BaseMapper一起玩。
参考链接:通用的BaseController
不过这位哥们的博客只给了个BaseController
和 BaseService
,也很不错了,就借鉴用一下:
BaseService
就直接用这位哥们的,BaseController
我自己改了一下:
package com.xiaocai.base.demo.common.base;
import com.github.pagehelper.PageInfo;
import com.xiaocai.base.demo.common.message.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 通用 BaseController
* @author Xiaocai.Zhang
* @param <T>
*/
@Slf4j
public abstract class BaseController<T> {
protected void beforeHandle(Map map){
log.info("前置处理--before");
}
protected void afterHandle(Map map){
log.info("后置处理--after");
}
/**
* 由子类的实现提供真实的service
* @return
*/
public abstract BaseService<T> getBaseService();
@RequestMapping("/add")
public Object add(@RequestBody Map map){
beforeHandle(map);
T newinstance = getBaseService().newinstance(map);
T t = getBaseService().add(newinstance);
afterHandle(map);
return CommonResult.ok("操作成功");
}
@RequestMapping("delete")
public Object delete(@RequestBody Map map){
T newinstance = getBaseService().newinstance(map);
getBaseService().delete(newinstance);
return CommonResult.ok("操作成功");
}
/**
* 通过主键id批量删除 参数必须为数组,名为ids
* @param ids
* @return
*/
@RequestMapping("deletes")
public Object batchDelete(@RequestParam("ids[]") Integer ids[]){
int i = getBaseService().deleteByIds(Arrays.asList(ids));
if(i>0) {
return CommonResult.ok("操作成功");
}else {
return CommonResult.fail("操作失败");
}
}
@RequestMapping("update")
public Object update(@RequestBody Map map){
T t = getBaseService().newinstance(map);
int rs = getBaseService().update(t);
if(rs>0) {
return CommonResult.ok("更新成功");
}else {
return CommonResult.fail("更新失败");
}
}
@RequestMapping("/getById")
public Object getById(@RequestParam(defaultValue = "1") Integer id){
T t = getBaseService().queryByPrimaryKey(id);
if(null==t)
return CommonResult.fail("查询失败");;
return CommonResult.ok(t);
}
@RequestMapping(value = "/getOne")
public Object getOne(@RequestBody Map map){
T t = getBaseService().newinstance(map);
t = getBaseService().queryOne(t);
if(null==t)
return CommonResult.fail("查询失败");;
return CommonResult.ok(t);
}
@RequestMapping("/getList")
public Object getList(@RequestBody Map map){
T t = getBaseService().newinstance(map);
List<T> list = getBaseService().queryList(t);
return CommonResult.ok(list);
}
/**
* 附带检索条件的分页查询
* @param map
* @param pageNo
* @param pageSize
* @return
*/
@RequestMapping("/getPageQuery")
public Object getListByPage(@RequestBody Map map, @RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize){
T t = getBaseService().newinstance(map);
PageInfo<T> pageInfo = getBaseService().queryListByPage(t,pageNo,pageSize);
return CommonResult.ok(pageInfo);
}
/**
* 无检索条件的分页查询 --测试过
* @param pageNo
* @param pageSize
* @return
*/
@RequestMapping("/getPage")
public Object getListByPage( @RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize){
//T t = getBaseService().newinstance(null);
T t=null;
PageInfo<T> pageInfo = getBaseService().queryListByPage(t,pageNo,pageSize);
return CommonResult.ok(pageInfo);
}
}
使用:
package com.xiaocai.base.demo.controller;
import com.xiaocai.base.demo.common.base.BaseController;
import com.xiaocai.base.demo.common.base.BaseService;
import com.xiaocai.base.demo.common.message.CommonResult;
import com.xiaocai.base.demo.service.base.UserBsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Xiaocai.Zhang
*/
@Slf4j
@RestController
@RequestMapping(value = "/user")
public class UserController extends BaseController {
@Autowired
private UserBsService userBsService;
@Override
public BaseService getBaseService() {
return userBsService;
}
/**
* http://localhost:8805/user/doUser
* @return
*/
@RequestMapping("/doUser")
public CommonResult doUser(){
return userBsService.querySpecialAgeOver20();
}
}
测试访问通用的查询:http://localhost:8805/user/getById
测试访问自定义的查询:http://localhost:8805/user/doUser
完整的Demo在这里: