5. ๐ Code Structure & Patterns
5.1 MVC Pattern Implementation
HONGIKINGAN CMS is implemented based on the Spring MVC pattern, with each layer clearly separated.
5.1.1 Controller Structure
Controllers receive client requests, call appropriate services, and pass results to views.
Main Features
- Request parameter validation
- Exception handling
- Response data formatting
- Implementation by inheriting HumanAbstractController
- Compliance with eGovFrame standard architecture
[Code Location] humanframe.backoffice.controller.bbs.AdminBbsController
@Controller
@RequestMapping("/${humanframe.admin.path}/bbs")
public class AdminBbsController extends HumanAbstractController {
@Resource(name="bbsSettingService")
private BbsSettingService bbsSettingService;
@Resource(name="siteService")
private SiteService siteService;
@Autowired
private MngrSession mngrSession;
@SuppressWarnings("unchecked")
@RequestMapping("list")
public String list(HttpServletRequest request, Model model) throws Exception {
HumanListVO listVO = new HumanListVO(request);
if(mngrSession.getAuthorTy().equals("2") || mngrSession.getAuthorTy().equals("3")){//Admin
listVO.setParam("siteNos", mngrSession.getSiteNos().length > 0?mngrSession.getSiteNos():new String[]{"0"});
listVO.setParam("crtrId",mngrSession.getMngrId());
if(mngrSession.getAuthorTy().equals("2")) {
listVO.setParam("bbsNos", "");
}else {
if(mngrSession.getSiteMenus() != null) {
listVO.setParam("bbsNos", mngrSession.getBbsNos().length > 0?mngrSession.getBbsNos():new String[]{"0"});
}else {
listVO.setParam("bbsNos", new String[] {"0"});
}
}
}
listVO = bbsSettingService.boardListVo(listVO);
List<BbsCtgryVO> bbsCtgryList = bbsSettingService.listCtgry(0, null, "BBS");
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("useAt", "Y");
List<SiteVO> siteList = siteService.selectSiteListAll(paramMap);
model.addAttribute("listVO", listVO);
model.addAttribute("useAt", CodeMap.USE_AT);
model.addAttribute("bbsTyCode", CommCodeMap.BBS_TY);
model.addAttribute("siteList", siteList);
model.addAttribute("bbsCtgryList", bbsCtgryList);
return "/admin/bbs/list";
}
// Other methods...
}
5.1.2 Service Layer
The service layer handles business logic and manages transactions.
Main Features
- Interface-based design
- Transaction management
- Business logic implementation
- DAO calls and result processing
- Implementation by inheriting EgovAbstractServiceImpl
- Compliance with eGovFrame standard architecture
[Code Location] humanframe.backoffice.service.BbsSettingService
@SuppressWarnings("rawtypes")
public interface BbsSettingService {
/**
* Retrieve board list.
*
* @param listVO Search conditions
* @return Board list
*/
public HumanListVO boardListVo(HumanListVO listVO) throws Exception;
/**
* Retrieve board information.
*
* @param bbsNo Board number
* @return Board information
*/
public BbsSettingVO retrieveBoardSetting(int bbsNo) throws Exception;
/**
* Retrieve board category list.
*
* @param bbsNo Board number
* @param prefix Prefix
* @param type Type
* @return Category list
*/
public List<BbsCtgryVO> listCtgry(int bbsNo, String prefix, String useTy) throws Exception;
// Other methods...
}
[Code Location] humanframe.backoffice.service.impl.BbsSettingServiceImpl
@SuppressWarnings("rawtypes")
@Service("bbsSettingService")
public class BbsSettingServiceImpl extends EgovAbstractServiceImpl implements BbsSettingService {
@Resource(name="bbsSettingDAO")
private BbsSettingDAO bbsSettingDAO;
@Resource(name="bbsScrtyDAO")
private BbsScrtyDAO bbsScrtyDAO;
@Override
public HumanListVO boardListVo(HumanListVO listVO) throws Exception {
return bbsSettingDAO.selectBoardListVO(listVO);
}
@Override
public BbsSettingVO retrieveBoardSetting(int bbsNo) throws Exception {
BbsSettingVO bbsSettingVO = bbsSettingDAO.selectBoardSetting(bbsNo, 0);
if(bbsSettingVO.getCtgryUseAt().equals("Y")) {
List<BbsCtgryVO> ctgryList = bbsSettingDAO.listCtgry(bbsNo, "L", "NTT");
bbsSettingVO.setCtgryList(ctgryList);
}
// ... Omitted (security configuration logic) ...
return bbsSettingVO;
}
@Override
public List<BbsCtgryVO> listCtgry(int bbsNo, String prefix, String useTy) throws Exception {
return bbsSettingDAO.listCtgry(bbsNo, prefix, useTy);
}
// Other methods...
}
5.1.3 DAO and MyBatis Utilization
DAO (Data Access Object) handles database interactions and uses MyBatis to manage SQL queries.
Main Features
- Interface-based mapper
- XML-based SQL management
- Dynamic query support
- Automated result mapping
- Implementation by inheriting HumanAbstractMapper which extends EgovAbstractMapper
- Compliance with eGovFrame standard architecture
[Code Location] humanframe.backoffice.dao.BbsSettingDAO
@Repository("bbsSettingDAO")
public class BbsSettingDAO extends HumanAbstractMapper {
public HumanListVO selectBoardListVO(HumanListVO listVO) throws Exception {
return selectListVO(setDomain("boardSetting.selectBoardCount"), setDomain("boardSetting.selectBoardListVO"), listVO);
}
public BbsSettingVO selectBoardSetting(int bbsNo, int siteNo) throws Exception {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("bbsNo", bbsNo);
if(siteNo > 0){
paramMap.put("siteNo", siteNo);
}
BbsSettingVO bbsSettingVO = (BbsSettingVO)selectOne(setDomain("boardSetting.selectBoardSetting"), paramMap);
return bbsSettingVO;
}
public List<BbsCtgryVO> listCtgry(int bbsNo, String prefix, String useTy) throws Exception {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("bbsNo", bbsNo);
paramMap.put("prefix", prefix);
paramMap.put("ctgryUseTy", useTy);
return selectList(setDomain("boardCtgry.listCtgry"), paramMap);
}
// Other methods...
}
[Code Location] humanframe/sqlmap/mappers/mysql/human-bbs-ctgry.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="humanframe.boardCtgry">
<resultMap type="bbsCtgryVO" id="bbsCtgryMap">
<result property="bbsNo" column="bbs_no" />
<result property="ctgryNo" column="ctgry_no" />
<result property="ctgryValue" column="ctgry_value" />
<result property="ctgryNm" column="ctgry_nm" />
</resultMap>
<select id="listCtgry" parameterType="hashmap" resultMap="bbsCtgryMap">
SELECT
bbs_no
, ctgry_no
<choose>
<when test="prefix != null">
, CONCAT('${prefix}-' , ctgry_no) AS ctgry_value
</when>
<otherwise>
, '' AS ctgry_value
</otherwise>
</choose>
, ctgry_nm
FROM tn_bbs_ctgry
WHERE bbs_no = #{bbsNo}
AND use_at = 'Y'
</select>
<!-- Other queries... -->
</mapper>
5.2 MVC Architecture Structure
The MVC architecture of HONGIKINGAN CMS complies with the eGovFrame standard architecture and has the following characteristics:
Controller Layer
- Complies with eGovFrame standard architecture
- Implemented by inheriting
HumanAbstractController - Controller classes cannot directly call DAO class methods
- Business logic processing through Service layer
View Layer
- Screen composition using JSP and Tiles
- Data representation using JSTL and EL
- Utilization of custom tag libraries
Model Layer
- Data transfer through VO (Value Object) classes
- Return results after business logic processing in Service layer
5.3 Service Architecture Structure
The service architecture of HONGIKINGAN CMS has the following characteristics:
Service Interface
- All services are defined as interfaces
- Interfaces located in "service" package
Service Implementation
- Implemented by extending
EgovAbstractServiceImpl - Implementations located in "service/impl" package
- Bean registration through
@Serviceannotation
Transaction Management
- Transaction management through
@Transactionalannotation - Declarative transaction management approach applied
5.4 Data Access Architecture Structure
The data access architecture of HONGIKINGAN CMS has the following characteristics:
DAO Classes
- Complies with eGovFrame standard architecture
- Implemented by inheriting
HumanAbstractMapperwhich extendsEgovAbstractMapper - Bean registration through
@Repositoryannotation
MyBatis Mapper
- XML-based SQL management
- Dynamic query support
- Support for various databases (CUBRID, Oracle, MySQL, MS-SQL, Tibero)
Database Connection
- JNDI-based datasource configuration
- Profile-specific datasource configuration (local, dev, prd)
5.5 AOP Utilization
HONGIKINGAN CMS utilizes Aspect-Oriented Programming (AOP) to modularize cross-cutting concerns such as logging and permission verification.
5.5.1 Logging
AOP is utilized to record system logs and user activity logs.
Main Features
- Controller method execution logging
- Service method execution time measurement
- Exception occurrence logging
- User activity logging
[Code Location] humanframe.backoffice.aop.aspect.admin.AdminLogAspect
@Aspect
@Order(2)
@Component
public class AdminLogAspect {
@Resource(name = "mngLogService")
private MngLogService mngLogService;
// Admin permission check
@Pointcut("execution(* humanframe.backoffice..Admin*Controller.form(..))"
+ "|| execution(* humanframe.backoffice..Admin*Controller.list(..))"
+ "|| execution(* humanframe.backoffice..Admin*Controller.view(..))"
+ "|| execution(* humanframe.backoffice..Admin*Controller.action(..))"
+ "|| execution(* humanframe.backoffice..Admin*Controller.logout(..))")
private void checkAdminLog() {}
@Before(value = "checkAdminLog()")
private void beforecheckAdminLog(
JoinPoint joinPoint)throws Exception {
// ... Omitted (admin log storage logic) ...
}
}
5.5.2 Permission Verification
AOP is utilized to verify access permissions for menus and functions.
Main Features
- Menu access permission verification
- Board permission verification
- Function permission verification
[Code Location] humanframe.backoffice.aop.aspect.admin.AdminBbsAspect
@Aspect
@Order(1)
@Component
public class AdminBbsAspect {
@Autowired
private BbsSettingService bbsSettingService;
@Autowired
private MngrSession mngrSession;
// Admin permission check
@Pointcut("execution(* humanframe.backoffice..AdminBbsType*Controller.form(..))"
+ "|| execution(* humanframe.backoffice..AdminBbsType*Controller.list(..))"
+ "|| execution(* humanframe.backoffice..AdminBbsType*Controller.view(..))"
+ "|| execution(* humanframe.backoffice..AdminBbsType*Controller.action(..))"
+ "|| execution(* humanframe.backoffice..AdminBbsType*Controller.answer(..))")
private void checkAdminBbsAuth() {}
@Before(value = "checkAdminBbsAuth()")
private void beforeCheckAdminBbsAuth(
JoinPoint joinPoint)throws Exception {
// ... Omitted (permission verification logic) ...
}
}
5.6 Interceptors and Filters
HONGIKINGAN CMS utilizes interceptors and filters to perform common tasks before and after request processing. This section explains the structural aspects of interceptors and filters. For detailed security-related content, please refer to the 07 Security Guide document.
5.6.1 Filter Structure
HONGIKINGAN CMS uses various filters registered in web.xml to enhance security and data preprocessing.
Filters operate at the servlet container level in a chain manner for all HTTP requests in the order defined in web.xml.
Main Filters and Application Paths
| Filter Name | Applied URL | Role/Description |
|---|---|---|
| CharacterEncodingFilter | /* |
Unify character encoding of all requests/responses to UTF-8 |
| HTMLTagFilter | /* |
Remove dangerous HTML tags from input parameters |
| CrossUrlScriptingFilter (XSS) | /* |
Prevent Cross-Site Scripting (XSS) attacks |
| XSSWebFilter | /* |
Additional XSS security filter (filter HTML and JS risk elements according to policy) |
| MberLoginFilter | /* |
Spring Security (DelegatingFilterProxy) based login processing |
| HumanFilter | /humanmst/* |
Admin page exclusive: Access control, authentication/authorization verification |
Filter Chain Structure
Client Request
โ
[CharacterEncodingFilter]
โ
[HTMLTagFilter]
โ
[CrossUrlScriptingFilter]
โ
[XSSWebFilter]
โ
[MberLoginFilter]
โ
[HumanFilter] (โป Only for admin page (/humanmst/*) requests)
โ
Servlet (DispatcherServlet, etc.)
Operational Reference
- Most filters are applied to all paths (
/*), whileHumanFilteris applied only to admin page (/humanmst/*) paths. - Filter execution order operates in the same order as registered in web.xml.
- HTML/XSS filters are applied hierarchically to maximize input value security.
- Login/authentication filters are placed at lower priority for security reasons.
5.6.2 Interceptor Structure
HONGIKINGAN CMS uses Spring MVC interceptors to apply common logic before/after HTTP request processing.
Main interceptors are registered in dispatcher-servlet.xml and have different paths and roles as follows.
Main Interceptors and Application Paths
| Interceptor Name | Applied Path | Role/Description |
|---|---|---|
| CMSUriInterceptor | Global (/), admin and some exceptions |
Site URI access control, unnecessary request blocking, etc. |
| CMSAdminInterceptor | Admin exclusive (/humanmst/, etc.) |
Admin page access exclusive, authentication and authorization check |
| DeviceResolverHandlerInterceptor | Global | (Spring Mobile) Device type (mobile/PC) identification |
Interceptor Chain Structure
Client Request
โ
[DeviceResolverHandlerInterceptor] (Mobile/PC distinction)
โ
[CMSUriInterceptor] (Site URI access management, excluding admin)
โ
[CMSAdminInterceptor] (โป Only for admin (/humanmst/, etc.) requests)
โ
Controller
Operational Reference
The application/exclusion paths of interceptors depend on the <mvc:interceptor> configuration in dispatcher-servlet.xml.