前后端分离的web项目-后端-springboot框架

创建项目时的选项

创建项目时的选项

结构目录
  • src/main/java
    • main
    • 前缀.aop
    • 前缀.controller
    • 前缀.entity
    • 前缀.ex
    • 前缀.interceptor
    • 前缀.mapper
    • 前缀.service
      • 前缀.service.impl
    • 前缀.thread
    • 前缀.webSocket
  • src/main/resources
    • mappers
    • application.properties
      #数据库路径
      spring.datasource.url = jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterCoding=utf-8&&serverTimezone=Asia/Shanghai
      #数据库用户名
      spring.datasource.username = root
      #数据库密码
      spring.datasource.password = root
      #上传文件最大限制
      spring.servlet.multipart.max-file-size = 100MB
      #mapper映射路径
      mybatis.mapper-locations = classpath:mappers/*.xml
      
步骤
  1. 创建所有目录结构、配置application.properties文件

  2. 启动类配置扫描注解

    #启动注解
    @SpringBootApplication
    #扫描mapper包
    @MapperScan("前缀.mapper")
    #扫描所有包
    @ComponentScan(basePackages = "前缀")
    
  3. 设计数据库、创建对应的实体类

    在‘前缀.entity’包下
    实体类需要实现Serializable接口

    implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
  4. 在‘前缀.mapper’包下创建对应数据库增删改查等功能的接口

  5. 创建对应mapper接口的实现功能的SQL语句的xml

    在‘mappers’目录下
    xml文件中添加约束

    <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
     "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
    
  6. 设计service异常类及其派生出的异常类

    在‘前缀.ex’包

    public class ServiceException extends RuntimeException{
    
    	/**
    	* 
    	*/
    	private static final long serialVersionUID = 1L;
    
    	public ServiceException() {
    		super();
    	}
    
    	public ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    		super(message, cause, enableSuppression, writableStackTrace);
    	}
    
    	public ServiceException(String message, Throwable cause) {
    		super(message, cause);
    	}
    
    	public ServiceException(String message) {
    		super(message);
    	}
    
    	public ServiceException(Throwable cause) {
    		super(cause);
    	}
    }
    
  7. 设计返回结果类型

    public class Result<T> implements Serializable {
    
    	/**
    	* 
    	*/
    	private static final long serialVersionUID = 1L;
    
    	private Integer state;
    	private String message;
    	private T data;
    	public Result(Integer state, Exception e) {
    		super();
    		this.state = state;
    		this.message = e.getMessage();
    	}
    	//以及get、set和根据属性的构造方法
    }
    
  8. 设计controller的基类(处理异常类)

    在‘前缀.controller’包

    /**
    * 控制器类的基类
    * @author Thomas Adam
    *
    */
    public class BaseController {
    
    	/**
    	* 处理请求时,用于表示操作正确的代码
    	*/
    	public static final int SUCCESS=200;
    	/**
    	* 处理用户数据请求时发生的异常
    	* @param e 异常
    	* @return 异常数据,处理结果
    	*/
    	@ExceptionHandler(ServiceException.class)
    	public Result<Void> handleException(Exception e){
    		//声明返回对象
    		Result<Void> rr=new Result<Void>();
    		//在返回对象中封装错误提示的文字
    		rr.setMessage(e.getMessage());
    		//根据异常的不同,返回的错误代码也不同
    		if(e instanceof UserConflictException) {
    			//用户名冲突
    			rr.setState(400);
    		}else if(e instanceof UserNotFoundException) {
    			//用户不存在
    			rr.setState(401);
    		}else if(e instanceof PasswordNotMatchException) {
    			//密码验证失败
    			rr.setState(402);
    		}else if(e instanceof TaskNotFoundException){
    			//用户没有任务信息
    			rr.setState(403);
    		}else if(e instanceof InsertException) {
    			//插入数据时发生异常
    			rr.setState(500);
    		}else if(e instanceof UpdateException) {
    			//更新数据时发生异常
    			rr.setState(501);
    		}else if(e instanceof NotLoginException) {
    			//未登录或登录信息失效
    			rr.setState(601);
    		}
    		//返回
    		return rr;
    	}
    	/**
    	* 从session中获取当前登录用户的ID
    	* @param session
    	* @return 当前登录用户的ID
    	*/
    	protected Integer getUidFromSession(HttpSession session) {
    		return Integer.valueOf(session.getAttribute("uid").toString());
    	}
    }
    
  9. 设计controller类、设计api接口

    在‘前缀.controller’包

    @RestController
    @RequestMapping("users")
    public class UserController extends BaseController
    
  10. 根据api接口,设计对应的接口及抽象方法

    在‘前缀.service’包
    抛出可能存在的异常

  11. 实现‘前缀.service’中的接口,编写具体步骤

    在‘前缀.service.impl’包
    实现类上加注解:@Service

  12. 调用service接口、完善controller类

  13. 设计websocket连接

    ‘前缀.webSocket’包

    • 连接处理类
      @ServerEndpoint(value="/webSocket/{uid}",configurator = HttpSessionConfigurator.class)
      @Component
      public class MyWebSocket {
      	//在线人数
      	private static int onlineCount=0;
      	
      	private static Map<Integer, MyWebSocket> socketMap = new ConcurrentHashMap<>();
      
      	private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<>();
      	
      	private Session session;
      	
      	@OnOpen
      	public void onOpen(Session session,@PathParam("uid") String uid) {
      		this.session = session;
      		sendMessage("连接成功!");
      		System.out.println("有新连接加入!");
      		Integer id = Integer.valueOf(uid);
      		socketMap.put(id, this);
      		addOnlineCount();
      		webSocketSet.add(this);
      		System.out.println("当前在线人数为:"+getOnlineCount());
      		System.out.println("用户ID:"+id);
      	}
      	@OnClose
      	public void onClose() {
      		if(webSocketSet.size()>=1) {
      			webSocketSet.remove(this);
      			for (Integer uid : socketMap.keySet()) {
      				MyWebSocket mws = socketMap.get(uid);
      				if(mws.equals(this)) {
      					socketMap.remove(uid);
      					break;
      				}
      			}
      		}
      		if(getOnlineCount()>=1)subOnlineCount();
      		System.out.println("有一连接关闭!当前在线人数为:"+getOnlineCount());
      	}
      	@OnMessage
      	public void onMessage(String message,Session session) {
      		System.out.println("来自客户端--"+session.getId()+"--的消息:"+message);
      	}
      	@OnError
      	public void onError(Session session,Throwable error) {
      		if(error instanceof NotLoginException)return;
      		System.err.println(error.getMessage());
      		System.out.println(error);
      	}
      	public synchronized void sendMessage(String message) {
      		try {
      			this.session.getBasicRemote().sendText(message);
      			System.out.println("---------向客户端发送信息----------");
      			System.out.println(message);
      			System.out.println("------------------------");
      		} catch (IOException e) {
      			e.printStackTrace();
      		}
      	}
      	public static  int getOnlineCount() {
      		return onlineCount;
      	}
      	private static synchronized void addOnlineCount() {
      		MyWebSocket.onlineCount++;
      	}
      	private static synchronized void subOnlineCount() {
      		MyWebSocket.onlineCount--;
      	}
      	public static synchronized CopyOnWriteArraySet<MyWebSocket> getWebSocketSet() {
      		return webSocketSet;
      	}
      	public static  Map<Integer, MyWebSocket> getSocketMap() {
      		return socketMap;
      	}
      	public Session getSession() {
      		return session;
      	}
      }
      
    • 配置类
      @Configuration
      public class WebSocketConfig {
      	@Bean
      	public ServerEndpointExporter serverEndpointExporter() {
      		return new ServerEndpointExporter();
      	}
      }
      
  14. 设计拦截器

    前缀.interceptor包

    • 未登录处理
      @Component
      public class LoginInterceptor implements HandlerInterceptor {
      
      	@Override
      	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      			throws Exception {
      		Object object = request.getSession().getAttribute("username");
      		if(object==null) {
      			throw new NotLoginException("请登录!");
      		}
      		return true;
      	}
      }
      
    • 拦截器
      @Configuration
      public class InterceptorConfiguration implements WebMvcConfigurer {
      	@Override
      	public void addInterceptors(InterceptorRegistry registry) {
      		//创建拦截器对象
      		HandlerInterceptor interceptor=new LoginInterceptor();
      		//白名单
      		List<String> list=new ArrayList<>();
      		list.add("/");
      		list.add("/users/reg");
      		list.add("/users/login");
      		//添加拦截器
      		registry.addInterceptor(interceptor).addPathPatterns("/**").excludePathPatterns(list);
      	}
      	/**
      	* (jar包)添加动态生成资源的路径
      	* 请求时转向此路径	
      	*/
      	@Override
      	public void addResourceHandlers(ResourceHandlerRegistry registry) {
      		registry.addResourceHandler("/excel/**").addResourceLocations("file:"+UploadPathUtils.getExcelPath());
      		WebMvcConfigurer.super.addResourceHandlers(registry);
      	}
      }
      
  15. 多线程(异步线程)

    '前缀.thread'包

    • 配置类
      //配置注解
      @Configuration
      //启动异步注解
      @EnableAsync
      public class ThreadConfig {
      	@Bean
      	public TaskExecutor taskExecutor() {
      		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      		//核心线程数量
      		executor.setCorePoolSize(1);
      		//最大线程数量
      		executor.setMaxPoolSize(1);
      		//任务队列
      		executor.setQueueCapacity(20);
      		return executor;
      	}
      }
      
    • 实现类
      @Component
      public class Hello {
      
      	@Async
      	public void sayHello(String name) {
      		System.err.println(System.currentTimeMillis());
      		System.err.println("处理任务中........");
      		try {
      			Thread.sleep(20000);
      		} catch (InterruptedException e) {
      			e.printStackTrace();
      		}
      		System.err.println(name+":Hello World!");
      	}
      }
      
  16. 切面编程

    '前缀.aop'包
    调用异步线程

    //切面注解
    @Aspect
    @Component
    public class AopTaskController {
    	@Autowired
    	//自动装配异步线程类
    
    	//切入点
    	@Pointcut(value = "execution(public * taobao.controller.TaskController.addNewTask(..))")
    	public void handleTask() {};
    	
    	@Pointcut(value = "execution(public * taobao.controller.TaskController.addGoodsTask(..))")
    	public void goodsTasks() {}
    	//切入点方法执行前执行
    	@Before("handleTask()")
    	public void berforeHandle() {
    	}
    	//切入点方法完成后执行
    	@AfterReturning(returning = "obj", pointcut = "handleTask()")
    	public void afterReturning(Object obj) {
    		handleDo(obj);
    	}
    	@AfterReturning(returning = "obj", pointcut = "goodsTasks()")
    	public void afterGoodsTask(Object obj) {
    		handleDo(obj);
    	}
    	private void handleDo(Object obj) {
    		//逻辑功能
    		//调用异步线程
    	}
    	
    }
    
posted @ 2020-12-30 15:47  牛五  阅读(151)  评论(0编辑  收藏  举报