1. SpringBoot框架搭建
(待编辑)
2. Mybatis逆向工程生成实体类、mapper及其映射文件
-
pom.xml引入Mybatis Generator Core依赖
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency>
-
resources路径下创建下generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 生成mysql带有分页的sql的插件 这个可以自己写,--> <!-- <plugin type="generator.MysqlPaginationPlugin" />--> <plugin type="org.mybatis.generator.plugins.ToStringPlugin" /> <plugin type="org.mybatis.generator.plugins.SerializablePlugin" /> <!--取消生成注释--> <commentGenerator> <property name="suppressDate" value="true"/> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--连接数据库--> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/demo" userId="root" password="123"> </jdbcConnection> <!--生成entity类存放位置--> <javaModelGenerator targetPackage="com.example.demo.entity" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!--生成映射文件存放位置--> <sqlMapGenerator targetPackage="com.example.demo.mapper" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!--生成Dao类存放位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.demo.dao" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!--需要逆向分析的表 表名+类名--> <table tableName="dishes" domainObjectName="Dishes"></table> <table tableName="dishorder" domainObjectName="DishOrder"></table> </context> </generatorConfiguration>
-
编写可执行方法
void testMBG() throws Exception { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); }
找不到文件问题:new File(绝对路径)
3. springboot集成shiro、JWT框架实现身份认证、角色授权
(待编辑)
4.springboot集成websocket
-
引入websocket相关依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
-
创建WebSocketConfig配置文件
@Configuration public class WebSocketConfig { /** * 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
-
创建WebSocketService文件,相当于一个工具类。既有四个和WeSocket连接状态相关的方法(onOpen、onClose、onMessage、onError),又有自定义的用于发送实时消息的一些静态方法
@ServerEndpoint(value = "/websocket/{userName}/{roleId}") @Component public class WebSocketService { private static final Logger log = LoggerFactory.getLogger(WebSocketService.class); //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。 private static ConcurrentHashMap<String, WebSocketClient> webSocketMap = new ConcurrentHashMap<>(); /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/ private Session session; /**接收userName*/ private String userName=""; /**接收roleId*/ private Integer roleId=-1; /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session, @PathParam("userName") String userName,@PathParam("roleId")Integer roleId) { if(!webSocketMap.containsKey(userName)) { addOnlineCount(); // 在线数 +1 } this.session = session; this.userName= userName; this.roleId = roleId; WebSocketClient client = new WebSocketClient(); client.setSession(session); client.setUri(session.getRequestURI().toString()); client.setRoleId(roleId); webSocketMap.put(userName, client); log.info("----------------------------------------------------------------------------"); log.info("用户连接:"+userName+"角色id"+roleId+",当前在线人数为:" + getOnlineCount()); sendAllMessage(userName,userName+"已登录"); } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { if(webSocketMap.containsKey(userName)){ webSocketMap.remove(userName); if(webSocketMap.size()>0) { //从set中删除 subOnlineCount(); } } log.info("----------------------------------------------------------------------------"); log.info(userName+"用户退出,当前在线人数为:" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String message, Session session) { log.info("收到用户消息:"+userName+",报文:"+message); //可以群发消息 //消息保存到数据库、redis // if(StringUtils.isNotBlank(message)){ // // } } /** * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("用户错误:"+this.userName+",原因:"+error.getMessage()); error.printStackTrace(); } /** * 连接服务器成功后主动推送 */ public void sendMessage(String message) throws IOException { synchronized (session){ this.session.getBasicRemote().sendText(message); } } /** * 向指定客户端发送消息 * @param userName * @param message */ public static void sendMessage(String userName,String message){ try { WebSocketClient webSocketClient = webSocketMap.get(userName); if(webSocketClient!=null){ webSocketClient.getSession().getBasicRemote().sendText(message); } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } } /** * 给所有人员发公告 * @param message */ public static void sendAllMessage(String userName,String message) { try { for (Map.Entry entry:webSocketMap.entrySet()) { // if (userName.equals(entry.getKey())) continue; WebSocketClient client = (WebSocketClient)entry.getValue(); client.getSession().getBasicRemote().sendText(message); } } catch (Exception e) { log.error("服务端发送消息给客户端失败", e); } } /** * 给厨师发送订单消息 * @return */ public static void sendMessageToCook(String message){ try{ for (WebSocketClient client: webSocketMap.values()){ if (client.getRoleId() != 2) continue; System.out.println("client's roleId"+client.getRoleId()); client.getSession().getBasicRemote().sendText(message); } }catch (Exception e){ log.error("给后厨发送消息失败!"); } } /** * 给服务员发送订单消息 * @return */ public static void sendMessageToWaiter(String message){ try{ for (WebSocketClient client: webSocketMap.values()){ if (client.getRoleId() != 3) continue; client.getSession().getBasicRemote().sendText(message); } }catch (Exception e){ log.error("给服务员发送消息失败!"); } } }
-
在需要发送实时消息的地方,调用工具类的静态方法
举例:管理员发布公告后,给除他自己以外的所有在线用户发送一条实时消息@RequestMapping("/add") @RequiresRoles("ADMIN") public boolean addDish(Notice notice){ notice.setSendTime(new Date()); WebSocketService.sendAllMessage(notice.getUserId(),"公告"); return noticeServiceImpl.addNotice(notice); }
-
前端完善相关代码
5. 问题总结
-
Mybatis中实体类属性名和数据库字段名不一致
eg:数据库 last_name 实体类 lastName
解决:
在mapper映射文件中创建resultMap<resultMap id="BaseResultMap" type="com.example.demo.entity.Dishes" > <!--主键--> <id column="id" property="id" jdbcType="INTEGER" /> <!--其余字段名--> <result column="dish_name" property="dishName" jdbcType="VARCHAR" /> <result column="price" property="price" jdbcType="DOUBLE" /> </resultMap>
-
@Autowired自动注入属性出错
解决:
先检查是否开启组件扫描
然后属性类型是否加了组件注解(@Component、@Mapper、@Service) -
只传入一个参数进行条件查询时,报错There is no getter for property named ‘id’ in ‘class java.lang.Integer’
解决:
xml文件中用_parameter指代这个唯一参数
<select id="getUser" parameterType="String"> select * from user <if test="_parameter != null and _parameter !=''"> where name = #{_parameter} </if> </select>
-
在mybatis进行多表查询
解决:
参考链接1
参考链接2
传入参数和输出参数类型都要变成Map
传入参数要利用@Param标明参数名public List<Map<String,Object>> findSomeDishOrder(@Param("dishName")String dishName, @Param("dishState")Integer dishState, @Param("tableId")Integer tableId, @Param("count")Integer count){ Map<String,Object> map = new HashMap<>(); map.put("dishName",dishName); map.put("dishState",dishState); map.put("tableId",tableId); map.put("count",count); List<Map<String,Object>> rs = dishOrderService.findSomeDishOrder(map); System.out.println(rs.size()); return dishOrderService.findSomeDishOrder(map); }
mapper映射文件
<select id="selectByTest" resultType="java.util.Map" parameterType="Map" >
SELECT distinct dish_name,table_id,dish_state,count
FROM dishes
INNER JOIN dishorder
ON dishes.dish_id = dishorder.dish_id
INNER JOIN orderinfo
ON dishorder.order_id = orderinfo.order_id
<trim prefix="where" suffixOverrides="and">
<if test="dishName != null and dishName != ''">
dish_name = #{dishName,jdbcType=VARCHAR} and
</if>
<if test="tableId != null">
table_id = #{tableId,jdbcType=INTEGER} and
</if>
<if test="dishState != null">
dish_state = #{dishState,jdbcType=INTEGER} and
</if>
<if test="count != null">
count = #{count,jdbcType=INTEGER} and
</if>
</trim>
</select>
6. 其他
- 结合springboot+mybatis+mysql进行增删查改
参考链接1
参考链接2 - shiro+springboot整合jwt进行身份验证、解决跨域问题
参考链接 - springboot配置打印sql语句
参考链接
application.ymlconfiguration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- 将springboot项目部署到服务器
参考链接1
参考链接2 - 规范!规范!规范!
团队之间涉及合作问题,如果一个人命名或者代码不规范,之后合并起来真的非常痛苦
务必重视!!!!!!!!!!!!!!
数据库规范:字段名不同单词之间用下划线分隔
类规范:成员属性名用小驼峰命名
springboot目录结构规范:
controller层
|
service层(用来声明方法的service接口类和具体实现方法的serviceImpl类)
|
mapper层(声明操作数据库方法名的mapper类和具体写sql语句的mapper映射文件xml) - 当不清楚跨越多个类、多个方法的执行顺序时,可以通过断点或者在每个方法内增加所属类所属方法名的控制台输出语句的方式进行分辨
- lombok使用
参考链接
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/75100.html